【发布时间】:2015-05-24 17:20:31
【问题描述】:
我想通过以下明显的示例执行虚拟继承:
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 中调用的内容的封装)。这里的单个参数是为了给这个“混蛋”构造函数一个唯一的签名。
// 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) {}
};
我的问题是:
如何避免使用虚拟继承调用过多参数化的构造函数?
是否可以通过其他方式改进“唯一签名”技术(例如使用枚举)?
有没有人有更好的技术来做同样的事情而不必在 A 中定义第二个构造函数?
有什么缺点?
【问题讨论】:
-
我引用:显而易见的不编译:class D : public B, public C { public: D(int x) : B(x), C(x) {} };这会产生一个错误,抱怨缺少 A 的默认构造函数。要完成这项工作,我们必须编写: D(int x) : A(x), B(x), C(x) {} 虽然这确实有效,这有点愚蠢,因为在为 D 对象调用时,在 B 和 C 构造函数中忽略了对 A 的初始化程序的调用。
-
你真正想解决什么编程问题?
-
您阅读了整篇文章吗?我的问题在最后。
-
“但我不想使用默认构造函数。” 为什么?
-
@dyp:好问题!我发现的解决方案确保在真正的构造函数中使用初始化列表,而不是默认构造函数,在我看来,这是一个概念变态。
标签: c++ constructor virtual-inheritance method-signature