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

Posted

技术标签:

【中文标题】使用 C++ 基类构造函数?【英文标题】:Using C++ base class constructors? 【发布时间】:2011-12-26 23:46:46 【问题描述】:

在使用模板时,我遇到了需要使基类构造函数可以从继承的类中访问以创建对象以减少复制/粘贴操作。 我正在考虑通过 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)'

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

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

【问题讨论】:

是的,你是对的。现已修复。 How to use base class's constructors and assignment operator in C++?的可能重复 【参考方案1】:

是的,从 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

【讨论】:

这对我不起作用。我得到一个“没有构造函数实例与参数列表匹配”。 @charlesrockbass 这意味着您的 B2 没有与您的参数列表匹配的构造函数,或者构造函数无法访问【参考方案2】:

不,不是这样的。初始化基类的常规方法是在初始化列表中:

class A

public: 
    A(int val) 
;

class B : public A

public:
  B( int v) : A( v )
  
  
;


void main()

    B b(10);

【讨论】:

【参考方案3】:

首选初始化:

class C : public A

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

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

更新:继承构造函数自 4.8 版开始在 GCC 中可用。


如果您觉得初始化不吸引人(例如,由于您的实际案例中存在多种可能性),那么对于某些 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;

【讨论】:

【参考方案4】:

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

class D : public A

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

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

C++11 允许您使用在 D 的声明中使用的 using A::A 语法,但目前并非所有编译器都支持 C++11 功能,因此最好坚持使用较旧的 C++方法,直到此功能在您的代码将使用的所有编译器中实现。

【讨论】:

你确定它可以编译吗? A 在第一个构造函数中是如何初始化的? 啊,是的,这个例子有点匆忙。现已修复。【参考方案5】:

这是关于superclass constructor calling rules 的一个很好的讨论。您总是希望在派生类构造函数之前调用基类构造函数,以便正确地形成对象。这就是为什么使用这种形式

  B( int v) : A( v )
  
  

【讨论】:

以上是关于使用 C++ 基类构造函数?的主要内容,如果未能解决你的问题,请参考以下文章

在其派生类C++的构造函数中调用基类的构造函数[重复]

C++中如何在子类的构造函数中调用基类的构造函数来初始化基类成员变量

C++中,继承时,创建子类对象,能否在子类构造函数初始化列表里调用基类构造函数?

C++基类和派生类的构造函数

C++如何使用派生类构造函数销毁基类中的对象

C++不是说虚基类构造函数只被调用一次吗?