简体   繁体   中英

Why aren't C++ constructors inherited?

Why is the Child pass-through constructor necessary in this code? I would think that it wouldn't be, but the compiler (gcc and VS2010) complains when I remove it. Is there an elegant workaround? It just seems pointless to have to insert this shim into child classes.

class Parent
{
public:
  Parent(int i) { }
};

class Child : public Parent
{
public:
  Child(int i) : Parent(i) { }
};

int main()
{
  Child child(4);
  return 0;
}

Because the following is perfectly valid:

class Parent
{
public:
    Parent(int i) { }
};

class Child : public Parent
{
public:
    Child() : Parent(42) { }
};

How is the compiler to guess whether you want the derived child to have a forwarded constructor? And in the case of multiple inheritance, the set of constructors from the two types may not match; when forwarding a constructor from base class A, which constructor on base class B should be called?

Technically, I suppose the language designers could have said that if the type has a single base class and in the absence of an explicit constructor, all parent constructors are forwarded. However, that creates the opposite problem: if a base class has multiple constructors including a default constructor, and the child wishes to allow only the default constructor, this must now be explicitly specified.

If you don't specify which parent constructor should be called explicitly, the compiler will generate code which calls the default (no-argument or with all default values) constructor.

In your case, the class Parent does not have such a constructor, the compiler would not know what value to use for i .

Not specifying a constructor in class Child means that the default constructor in class Parent would be called but this does not exist.


I haven't tried it but have a look at this section of the C++0x FAQ . I have the impression what you're asking for is possible in C++0x.

It's because in C++ you have multiple inheritance. In the following example, which constructor should be inherited?

class Parent1
{
public:
  Parent1(int i) { }
};

class Parent2
{
public:
  Parent2(int i) { }
};

class Child : public Parent1, public Parent2
{
};

Is there an elegant workaround?

Since C++11, you can use a using declaration to inherit constructors (not including default, copy or move constructors) from a base:

class Parent
{
public:
  Parent(int i) { }
};

class Child : public Parent
{
public:
  using Parent::Parent; // inherits Parent(int)
};

int main()
{
  Child child(4);
  return 0;
}

Here's another case

class Parent
{
public:
  Parent(int i) {this.i = i; }
  Parent() {this.i = 0;}
private:
  int i;
};

class Child : public Parent
{
public:
  Child(int i) : { }
};

int main()
{
  Child child(4);
  return 0;
}

Given that, which Parent constructor should be called. What if Parent defines a constructor that takes in a long but not one that takes an int ? Should the compiler auto-convert the int to long ?

For better or worse, the language designers opted for simplicity -- the only constructor that is automatically called from a derived class is the default (no-arg or all args having defaults) constructor. Everything else needs to be explicitly called.

The compiler only autogenerates the default constructor, that is the ctr without parameters, but only if you haven't defined any constructors.

In this case, you have (in the parent), so no default is made for you, plus the child needs it so that it knows what to do with the parameter i that you are passing to it.

Constructors need to be called explicitly by the child constructor if you don't want to use the default one which generated by compiler, which is called default constructor (the one with no arguments). But apparently in your case you want a constructor that accepts an int , then you have to call it explicitly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM