The technical term for a class with a pure virtual function is abstract class, but that terms also applies if the class has additional non-pure virtual functions.
Often the term Interface is used in C++ to describe an abstract class like Printable
, that describes a service that can be provided by a range of different, otherwise unrelated classes. This corresponds to the use of the interface
keyword in C#/Java.
I have never encountered the term 'protocol' in connection with a C++ class
You're right, this is a flaw in the language itself which means that despite all the advantages which come from inheritance, you still have to know how it is implemented. It would be ideal to be able to call super within the method and have it call the appropriate method, whatever that might be. This is one of the things that Java tried to improve upon.
As you said, you could get around it by implementing every method in class A, and so in doing so, you prevent complications later on. It is a bit of a pain, but I suppose it is a necessary evil for creating a proper library to be used by others. Note that only the class being made available in the library for use has to implement all virtual methods, and not any internally used classes unless you require otherwise.
While not a solution, a slightly friendlier approach (albeit a little hacky) might be to typedef "super" as a private type definition for the base class. As in the case of class B, you'd have:
private:
typedef A super;
Likewise in class A, you could define:
private:
typedef Base super;
At least if you're the one writing the code, rather than have to know the name of the class, you could do:
class B : A
{
void foo(bool param) override
{
// do some stuff here.
super::foo(param);
}
void foo1(int param) override
{
super::super::foo1(1);
}
};
Again, while this doesn't fix your problem, it makes it slightly more manageable.
See here for more details.
Best Answer
C++ has a rule about overridden functions: they don't have to be explicitly declared as
virtual
. Consider your example withoutoverride
:double getAge(int id);
. If there is a base class function declaredvirtual
, namedgetAge
, and takes the same parameters as the derived class function, then the derived class function will implicitly bevirtual
and it will be an override for that function.However, what happens if you make a mistake? Let's say that you mistype the derived function name as
gtAge
. Well, if there isn't an override-able base class function... then that will declare a non-virtual
function which overrides nothing. It remains a perfectly valid function declaration. The user made a mistake, but the compiler had no way to know. Even adding thevirtual
keyword doesn't solve this, as it's perfectly valid to add newvirtual
functions to a derived class.Now, in your specific case, compilation will still fail. You declared the base class function as pure-virtual, so a derived class which doesn't override it cannot be instantiated. But even then, the error won't point directly at the line causing the problem; it won't point at the
gtAge
. Instead you'll get a "cannot instantiate due to no overriddengetAge
" error; the user will have to figure out where the derived class failed to override this function.But if the base class function was not pure-virtual, then you're completely out of luck. You'll get highly unexpected behavior and it will take a while to figure out where you went wrong.
Enter
override
. This tells the compiler that you specifically intend this declaration to override a base classvirtual
function. So if the compiler doesn't find a matching function in a base class, the compiler will error out immediately, telling you exactly where you went wrong.You may be getting confused by the fact that
double getAge(int id)
actually returns a different type from what it overrides. This is actually (unfortunately, in my opinion) perfectly valid. Overridden return types can be any type which is convertible to the return type of the base class function being overridden.