Professional C__ - Marc Gregoire [124]
class Sub : public Super
{
public:
Sub();
virtual void someMethod(double d);
};
You can call someMethod() through a reference as follows:
Sub mySub;
Super& ref = mySub;
ref.someMethod(1); // Calls Sub's version of someMethod()
This will correctly call the overridden someMethod() from the Sub class. Now, suppose you used an integer parameter instead of a double while overriding someMethod() as follows:
class Sub : public Super
{
public:
Sub();
virtual void someMethod(int i);
};
As seen in the previous section, this code will not override someMethod(), but will instead create a new virtual method. If you try to call someMethod() through a reference as in the following code, someMethod() of Super will be called instead of the one from Sub.
Sub mySub;
Super& ref = mySub;
ref.someMethod(1); // Calls Super's version of someMethod()
This type of problem can happen when you start to modify the Super class but forget to update all subclasses. For example, maybe your first version of the Super class had a method called someMethod() accepting an integer. You then wrote the Sub subclass overriding this someMethod() accepting an integer. Later you decide that someMethod() in the Super class needs a double instead of an integer, so you update someMethod() in the Super class. It might happen that at that time, you forget to update the someMethod() methods in subclasses to also accept a double instead of an integer. By forgetting this, you are now actually creating a new virtual method instead of properly overriding the method.
You can prevent this situation by using the override keyword as follows:
class Sub : public Super
{
public:
Sub();
virtual void someMethod(int i) override;
};
This definition of Sub will generate a compiler error, because with the override keyword you are saying that someMethod() is supposed to be overriding a method from the Super class, but in the Super class there is no someMethod() accepting an integer, only one accepting a double.
Inherited Constructors
In an earlier section you saw the use of the using keyword to explicitly include the superclass definition of a method within a subclass. This works perfectly for normal class methods, however, prior to C++11, it did not work for constructors. C++11 solves this and allows you to inherit base class constructors in your subclasses. Take a look at the following definition for the Super and Sub classes:
class Super
{
public:
Super(const std::string& str);
};
class Sub : public Super
{
public:
Sub(int i);
};
You can construct a Super object only with the provided Super constructor, which requires a string as parameter. On the other hand, constructing a Sub object can happen only with the provided Sub constructor, which requires a single integer as parameter. You cannot construct Sub objects by using the constructor accepting a string defined in the Super class. For example:
Super super("Hello"); // OK, calls string based Super ctor
Sub sub1(1); // OK, calls integer based Sub ctor
Sub sub2("Hello"); // Error, Sub does not inherit string Super ctor
If you would like the ability to construct Sub objects using the string based Super constructor, you can explicitly inherit the Super constructors in the Sub class as follows:
class Sub : public Super
{
public:
using Super::Super;
Sub(int i);
};
Now you can construct Sub objects in the following two ways:
Sub sub1(1); // OK, calls integer based Sub ctor
Sub sub2("Hello"); // OK, calls inherited string based Super ctor
The Sub class can define a constructor with the same parameter list as one of the inherited constructors in the Super class. In this case, as with any override, the constructor of the Sub class takes precedence over the inherited constructor. In the following example, the Sub class inherits all constructors from the Super class with the using keyword. However, since the Sub class defines its own constructor with a single argument of type float, the inherited constructor from the Super class with a single argument of type float is overridden.
class Super