Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inherited constructors ignore in-class initialization

I have a class defined like this:

class ASTConcatenateLiteral : public ASTExpr {
    using ASTExpr::ASTExpr;
private:
    Type type_ = Type::nothingness();  // Type does not have a default constructor
};

This works fine with Clang. GCC, however, gives me an error message that makes me think it’s trying to use the default initializer:

error: no matching function for call to ‘EmojicodeCompiler::Type::Type()’

If I replace using ASTExpr::ASTExpr; with a public constructor like this (ASTExpr only provides exactly this constructor)

ASTConcatenateLiteral(const SourcePosition &p) : ASTExpr(p) {}

everything works fine.

According to cppreference.com:

The inherited constructors are equivalent to user-defined constructors with an empty body and with a member initializer list consisting of a single nested-name-specifier, which forwards all of its arguments to the base class constructor.

So why doesn’t the inherited constructor work? If the inherited constructor behaves like a user-defined constructors, it should use the value provided for type_, right? Which of the compilers is right according to the standard?

like image 905
idmean Avatar asked Aug 22 '17 08:08

idmean


People also ask

Do I need to override a constructor in C++?

Only if the method is pure virtual at this level, it is undefined behavior calling it from the constructor/destructor. In Java, in the other hand, you must not call any overriden method in the constructor as that will be dispatched to the most derived class that has not yet been initialized.

How to inherit a constructor c++?

To inherit only selected ones you need to write the individual constructors manually and call the base constructor as needed from them. Historically constructors could not be inherited in the C++03 standard. You needed to inherit them manually one by one by calling base implementation on your own.

Are base class constructors inherited?

In inheritance, the derived class inherits all the members(fields, methods) of the base class, but derived class cannot inherit the constructor of the base class because constructors are not the members of the class.

Can we override constructor in derived class?

No we cannot override the constructor. A constructor is a special member function of class with the same name as that of class. Its primary purpose is to initialize the data members of the instance of the class. Hence saying that it initializes the data members of the class would be wrong.


1 Answers

Clang is correct. When inherited constructor is used, the initialization should proceed as if a defaulted default constructor were used to initialize the object of the derived class, thus the default member initializers should be used.

(emphasis mine)

If overload resolution selects one of the inherited constructors when initializing an object of such derived class, then the Base subobject from which the constructor was inherited is initialized using the inherited constructor, and all other bases and members of Derived are initialized as if by the defaulted default constructor (default member initializers are used if provided, otherwise default initialization takes place).

Here's an example from the standard:

struct B1 {
  B1(int, ...) { }
};

struct B2 {
  B2(double) { }
};

int get();

struct D1 : B1 {
  using B1::B1;     // inherits B1(int, ...)
  int x;
  int y = get();
};

void test() {
  D1 d(2, 3, 4);    // OK: B1 is initialized by calling B1(2, 3, 4),
                    // then d.x is default-initialized (no initialization is performed),
                    // then d.y is initialized by calling get()
  D1 e;             // error: D1 has a deleted default constructor
}

Note that d.y is initialized by the default member initializer.

like image 66
songyuanyao Avatar answered Sep 21 '22 15:09

songyuanyao