Online Book Reader

Home Category

Professional C__ - Marc Gregoire [125]

By Root 1537 0

{

public:

Super(const std::string& str);

Super(float f);

};

class Sub : public Super

{

public:

using Super::Super;

Sub(float f); // Overrides inherited float based Super ctor

};

With this definition, objects of Sub can be created as follows:

Sub sub1("Hello"); // OK, calls inherited string based Super ctor

Sub sub2(1.23); // OK, calls float based Sub ctor

A few restrictions apply to inheriting constructors from a base class with the using clause. When you inherit a constructor from a base class, you inherit all of them. It is not possible to inherit only a subset of the constructors of a base class. A second restriction is related to multiple inheritance. It’s not possible to inherit constructors from one of the base classes if another base class has a constructor with the same parameter list, because this will lead to ambiguity. To resolve this, the Sub class needs to explicitly define the conflicting constructors. For example, the following Sub class tries to inherit all constructors from both the Super1 and Super2 class, which results in a compiler error due to ambiguity of the float based constructors.

class Super1

{

public:

Super1(float f);

};

class Super2

{

public:

Super2(const std::string& str);

Super2(float f);

};

class Sub : public Super1, public Super2

{

public:

using Super1::Super1;

using Super2::Super2;

Sub(char c);

};

The first using clause in Sub inherits the constructors from Super1. This means that Sub will get the following constructor:

Sub(float f); // Inherited from Super1

With the second using clause in Sub you are trying to inherit all constructors from Super2. However, this will generate a compiler error because this would mean that Sub gets a second Sub(float f) constructor. The problem is solved by explicitly declaring conflicting constructors in the Sub class as follows:

class Sub : public Super1, public Super2

{

public:

using Super1::Super1;

using Super2::Super2;

Sub(char c);

Sub(float f);

};

The Sub class now explicitly declares a constructor with a single argument of type float, solving the ambiguity. If you want, this explicitly declared constructor in the Sub class accepting a float parameter can still forward the call to the Super1 and Super2 constructors in its ctor-initializer as follows:

Sub::Sub(float f) : Super1(f), Super2(f) {}

When using inherited constructors, make sure that all member variables are properly initialized. For example, take the following new definitions for the Super and Sub classes. This example does not properly initialize the mInt data member in all cases which is a serious error. These cases and a solution will be given after the example.

class Super

{

public:

Super(const std::string& str) : mStr(str) {}

protected:

std::string mStr;

};

class Sub : public Super

{

public:

using Super::Super;

Sub(int i) : Super(""), mInt(i) {}

protected:

int mInt;

};

You can create a Sub object as follows:

Sub s1(2);

This will call the Sub(int i) constructor, which will initialize the mInt data member of the Sub class and call the Super constructor with an empty string to initialize the mStr data member.

Because the Super constructor is inherited in the Sub class, you can also construct a Sub object as follows:

Sub s2("Hello World");

This will call the inherited Super constructor in the Sub class. However, this inherited Super constructor only initializes the mStr member variable of the Super class and does not initialize the mInt member variable of the Sub class, leaving it in an uninitialized state. This is usually not recommended.

The solution is to use another C++11 feature called in-class member initializers, which are discussed in Chapter 6. The following code uses an in-class member initializer to initialize mInt to 0. The Sub(int i) constructor can still change this initialization and initialize mInt to the constructor argument i.

class Sub : public Super

{

public:

using Super::Super;

Sub(int i) : Super(""), mInt(i) {}

protected:

int mInt = 0;

};

Special Cases in Overriding Methods

Several special

Return Main Page Previous Page Next Page

®Online Book Reader