我想用以下明显的例子执行虚拟继承:
class A
{
public:
A(int a) : m_a(a) {}
private:
int m_a;
};
class B : virtual public A
{
public:
B(int a, int b) : A(a), m_b(b) {}
private:
int m_b;
};
class C : virtual public A
{
public:
C(int a, int c) : A(a), m_c(c) {}
private:
int m_c;
};
class D : public B, public C
{
public:
D(int a, int b, int c) : A(a), B(a, b), C(a, c) {}
};
但是我不想调用B(a,b)和C(a,c),因为参数a在B和C构造函数中对于这种特殊的虚拟继承情况是无用的。
我找到了以下文章,其中Jack Reeves提出了一些替代方法,以便调用默认构造函数。
http://www.drdobbs.com/cpp/multiple-inheritance-considered-useful/184402074?pgno=2
引用:
如果我们必须在B和C之前完全初始化A,那么我们必须使用构造函数进行初始化,然后我们回到我最初展示的内容。或者,也许您可以使用以下内容:
class B : public virtual A { // class C is similar
public:
B(int x) : A(x) {}
protected:
B() : A(0) {}
};
class D : public B, public C {
public:
D(int x) : A(x) {} // B and C are default constructed
};
引用结束。
所以,我保留了受保护构造函数的想法,但我不想使用默认构造函数。我在A中实现了一个奇异的参数构造函数(在实践中从未调用过),它使用正向构造函数来实现最简单的"类中的有效构造函数(保持B和C应该在A中调用的封装)。单个参数在这里为这个" bastard"提供了一个独特的签名。构造
// new way
namespace VIRTUAL_INHERITANCE {
struct NEVER_CALLED {};
}
class A
{
public:
A(int a) : m_a(a) {}
protected:
A(VIRTUAL_INHERITANCE::NEVER_CALLED vinc) : A(0) {}
private:
int m_a;
};
class B : virtual public A
{
public:
B(int a, int b) : A(a), m_b(b) {}
protected:
B(int b) : A(VIRTUAL_INHERITANCE::NEVER_CALLED()), m_b(b) {}
private:
int m_b;
};
class C : virtual public A
{
public:
C(int a, int c) : A(a), m_c(c) {}
protected:
C(int c) : A(VIRTUAL_INHERITANCE::NEVER_CALLED()), m_c(c) {}
private:
int m_c;
};
class D : public B, public C
{
public:
D(int a, int b, int c) : A(a), B(b), C(c) {}
};
我的问题是:
如何避免使用虚拟继承调用过多的参数化构造函数?
是否有可能改善"独特的签名"做其他事情的技术(例如用enum)?
是否有人有更好的技巧来做同样的事情而不必在A中定义第二个构造函数?
有什么缺点?
答案 0 :(得分:0)
我的回答是:
enum
,A
的构造函数,那么您必须声明其他构造函数。但是,如果你没有......使用默认构造函数和init
函数或只是一个常规的参数化构造函数,A
中的更多代码,B
中的更多代码,C
中的更多代码,init
函数或参数化构造函数示例(整洁)代码:
class A
{
public:
A(int a) : m_a(a) {}
protected:
A() = default;
void initA(int a) { m_a = a; } // optional
private:
int m_a;
};
class B : virtual public A
{
public:
B(int a, int b) : A(a), m_b(b) {}
protected:
B(int b) : m_b(b) {}
private:
int m_b;
};
class C : virtual public A
{
public:
C(int a, int c) : A(a), m_c(c) {}
protected:
C(int c) : m_c(c) {}
private:
int m_c;
};
class D : public B, public C
{
public:
D(int a, int b, int c) : A(a), B(b), C(c) {}
// or optionally:
D(int a, int b, int c) : B(b), C(c) { initA(a); }
};