如何避免使用虚拟继承调用过多的参数化构造函数?
How to avoid calling a too much parameterized constructor, with virtual inheritance?
我想使用以下明显的示例执行虚拟继承:
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 中实现了一个单参数构造函数(在实践中从未调用过),它使用前向构造函数指向 class 中的 "simpliest" 有效构造函数(保持 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) {}
};
我的问题是:
如何使用虚拟继承避免调用过多的参数化构造函数?
是否可以改进 "unique signature" 技术来做其他事情(例如枚举)?
有没有人有更好的技术来做同样的事情而不必在 A 中定义第二个构造函数?
有什么缺点?
我的答案是:
- 使用默认构造函数,
- 是的,可以使用
enum
、
- 没有。如果您希望编译器强制您显式调用
A
的构造函数,那么您必须声明 附加构造函数。但是,如果您不...使用默认构造函数和 init
函数 或 只是一个常规的参数化构造函数,
- 具有"unique signature"构造函数的缺点:
- 更多代码在 class
A
,
- 更多代码在 class
B
,
- 更多代码在 class
C
,
- 由于虚拟结构,代码较多。
- 使用 "init" 函数的默认 c-tor 的缺点:
- 你必须记得调用
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); }
};
我想使用以下明显的示例执行虚拟继承:
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 中实现了一个单参数构造函数(在实践中从未调用过),它使用前向构造函数指向 class 中的 "simpliest" 有效构造函数(保持 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) {}
};
我的问题是:
如何使用虚拟继承避免调用过多的参数化构造函数?
是否可以改进 "unique signature" 技术来做其他事情(例如枚举)?
有没有人有更好的技术来做同样的事情而不必在 A 中定义第二个构造函数?
有什么缺点?
我的答案是:
- 使用默认构造函数,
- 是的,可以使用
enum
、 - 没有。如果您希望编译器强制您显式调用
A
的构造函数,那么您必须声明 附加构造函数。但是,如果您不...使用默认构造函数和init
函数 或 只是一个常规的参数化构造函数, - 具有"unique signature"构造函数的缺点:
- 更多代码在 class
A
, - 更多代码在 class
B
, - 更多代码在 class
C
, - 由于虚拟结构,代码较多。
- 更多代码在 class
- 使用 "init" 函数的默认 c-tor 的缺点:
- 你必须记得调用
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); }
};