使用 C + + 基类构造函数?

在使用模板的时候,我遇到了一个需要,为了减少复制/粘贴操作,需要让基类构造函数可以从继承的类中访问以创建对象。 我一直在考虑通过 using关键字以相同的方式实现函数大小写,但是没有用。

class A
{
public:
A(int val) {}
};


class B : public A
{
};


class C : public A
{
public:
C(const string &val) {}
};


class D : public A
{
public:
D(const string &val) {}
using A::A;              // g++ error: A::A names constructor
};


void main()
{
B b(10);                // Ok.   (A::A constructor is not overlapped)
C c(10);                // error: no matching function to call to 'C::C(int)'
}

因此,我的问题是: 在继承类中的新构造函数被声明之后,有没有办法导入基类构造函数?

或者只有一种方法可以声明新的构造函数并从初始化器列表中调用基本构造函数?

135112 次浏览

首选初始化:

class C : public A
{
public:
C(const string &val) : A(anInt) {}
};

在 C + + 11中,您可以使用继承构造函数(具有在示例 D中看到的语法)。

Update: Inheriting Constructors have been available in GCC since version 4.8.


如果您觉得初始化没有吸引力(例如,由于实际情况中可能性的数量) ,那么您可能会倾向于使用这种方法来实现一些 TMP 构造:

class A
{
public:
A() {}
virtual ~A() {}
void init(int) { std::cout << "A\n"; }
};


class B : public A
{
public:
B() : A() {}
void init(int) { std::cout << "B\n"; }
};


class C : public A
{
public:
C() : A() {}
void init(int) { std::cout << "C\n"; }
};


class D : public A
{
public:
D() : A() {}
using A::init;
void init(const std::string& s) { std::cout << "D -> " << s << "\n"; }
};


int main()
{
B b; b.init(10);
C c; c.init(10);
D d; d.init(10); d.init("a");


return 0;
}

No, that's not how it is done. Normal way to initialize the base class is in the initialization list :

class A
{
public:
A(int val) {}
};


class B : public A
{
public:
B( int v) : A( v )
{
}
};




void main()
{
B b(10);
}

您需要在每个派生类中声明构造函数,然后从初始值设定项列表中调用基类构造函数:

class D : public A
{
public:
D(const string &val) : A(0) {}
D( int val ) : A( val ) {}
};


D variable1( "Hello" );
D variable2( 10 );

C + + 11允许你使用 A: : A 语法,你在 D 的声明中使用,但是 C + + 11的特性并不是现在所有的编译器都支持的,所以最好坚持使用旧的 C + + 方法,直到这个特性在你的代码所使用的所有编译器中得到实现。

这里有一个关于 超类构造函数调用规则的很好的讨论。您总是希望基类构造函数被称为 之前派生类构造函数,以便正确地形成对象。这就是为什么要用这个表格

  B( int v) : A( v )
{
}

是的,因为 C + + 11:

struct B2 {
B2(int = 13, int = 42);
};
struct D2 : B2 {
using B2::B2;
// The set of inherited constructors is
// 1. B2(const B2&)
// 2. B2(B2&&)
// 3. B2(int = 13, int = 42)
// 4. B2(int = 13)
// 5. B2()


// D2 has the following constructors:
// 1. D2()
// 2. D2(const D2&)
// 3. D2(D2&&)
// 4. D2(int, int) <- inherited
// 5. D2(int) <- inherited
};

有关更多信息,请参见 http://en.cppreference.com/w/cpp/language/using_declaration

class A
{
public:
A(int val) {}
A(string name) {}
};


class B : public A
{
using A::A;
};

除了其他答案之外,如果有几个构造函数具有基类,并且您只想继承其中的一些构造函数,则可以删除不需要的构造函数。

 class B : public A
{
using A::A;
B(string) = delete;
};