Function override and overload in C++ and Delphi
Spacesoft【Dark Night Sand】
In object-oriented programming, when the subclass continues the functions from the base class, the subclass may need to deal with some of the functions differently from the base class, such as:
class CHuman
{
public:
void SayMyName()//Print out the object's name
{
cout << Hi, I am a human << endl;
}
};
Then it is obvious, if its subclass has a function SayMyName with the same name, same parameter and return value (one sentence, the same function), which function will it call? For example, there is a class CMark now
class CMark: public CHuman
{
public:
void SayMyName()
{
cout << Hi, I am mark << endl;
}
};
Then we have to ask, the following program segment:
CHuman *pH = new CMark;
if (pH)
pH->SayMyName();
else
cout << cast error! << endl;
delete pH;
pH = NULL;
Is the Hi, I am mark we want to print out?
no. It outputs Hi, I am a human. It's awful, and when we point at a person and ask him to say his name, he tells us that he is "a person" rather than saying his name. The reason for this problem is that pointing to the public derived class with the base class pointer, you can access the member functions of the derived class that continue from the base class. But if there are functions with the same name in the derived class, the result is still accessing the function of the same name of the base class, rather than the function of the derived class itself. In fact, what we want is to determine which of these functions of the same name should be called by the real type of an object, that is, such a resolution is dynamic. Or we can say that when an object is a subtype, its implementation of the same name in the subclass overrides the implementation of the base class.
Let's start with C++'s handling of this problem.
This is a typical example of polymorphism in C++. C++ uses virtual functions to implement such polymorphism. To be specific, it is to use virtual key words to describe the function as a virtual function. In the previous example, it should be declared as:
class CHuman
{
public:
virtual void SayMyName()//Print out the object's name
{
cout << Hi, I am a human << endl;
}
};
In this way, other codes are still the same, but our CMark already knows how to say its name. It doesn't matter whether the SayMyName() function of CMark has added a virtual key word, because according to the provisions of C++ syntax, because it overrides the CHuman function of the same name, it becomes virtual itself. As for why a virtual key word has such a magical effect? C++ FAQ Lite explains this as follows: In C++, "virtual member functions are dynamically determined (at runtime). That is, member functions (at runtime) are dynamically selected, and the selection is based on the type of the object. , not the type of pointer/reference to that object". So our pH finds that it actually points to an object of type CMark, not the CHuman declared by its own type, so it cleverly calls CMark's SayMyName.
Delphi uses override key words to illustrate function overrides. The overwritten function must be virtual or dynamic, that is, the function should contain one of these two indicators when declared, such as:
PRocedure Draw; virtual;
When you need to override, you just need to redeclare it with the override indicator in the subclass.
procedure Draw; override;
Syntactically, declarations as virtual and dynamic are equivalent. The difference is that the former optimizes speed in implementation, while the latter optimizes code size.
What if both the base class and the subclass contain the same function name and parameter, and the override indicator is not added to the subclass? This is also syntactically correct. This means that the function implementation of the subclass's function hides the base class's implementation, although both exist in the derived class. Then let’s go back to the situation shown in the first example at the beginning of this article: When we point to a person and ask him to say his own name, he tells us that he is "a person", rather than saying his own name.
It is worth noting that unlike the overloading function and overloading function that we often call overloading in C++, in Delphi, only overloading is what we usually call overloading. The overloaded function still exists, and the parameters are used to determine which implementation is called. Of course, when the function dropped overload is the same as the function parameters of the base class, the implementation of the base class is hidden, just like the one mentioned above. Override means making the overwritten function invisible and indeed overwrite, and the original implementation will disappear. For this reason, many articles and even some books have mistakenly translated override into overload, which I think is not appropriate.