qdo*_*dot 3 c++ inheritance constructor
在场景中:
class A : public B {
private:
C m_C;
public:
A();
}
Run Code Online (Sandbox Code Playgroud)
是
A::A() :
m_C(5),
B(m_C)
{}
Run Code Online (Sandbox Code Playgroud)
法律?之后会B::B(m_C)被调用C::C(int)吗?如果是这样,我该怎么办才能避免呢?
这是如何实现的:
class MyValidator : public QRegExpValidator {
private:
QRegExp myRegExp;
public:
MyValidator();
virtual void fixup(QString &f);
}
MyValidator::MyValidator()
QRegExpValidator(QRegExp("foo"));
{}
void MyValidator::fixup(QString &f){
// A QRegExp("foo") is also needed here.
}
Run Code Online (Sandbox Code Playgroud)
我已经发现了
const QRegExp & QRegExpValidator::regExp() const;
Run Code Online (Sandbox Code Playgroud)
这减轻了我自己引用的需要myRegExp,所以我的特定问题就解决了..
还有什么是最好的模式,如果QRegExpValidator没有这样的功能来检索它的初始化程序..手动管道所有的功能到成员类,而不是继承?
这就是C++ 11标准所说的([class.base.init]/10):
在非委托构造函数中,初始化按以下顺序进行:
- 首先,仅对于派生程度最高的类(1.8)的构造函数,虚拟基类按它们在深度优先左侧出现的顺序进行初始化.正确遍历基类的有向非循环图,其中"从左到右"是派生类base-specifier-list中基类出现的顺序.
- 然后,直接基类按声明顺序初始化,因为它们出现在base-specifier-list中(无论mem-initializers的顺序如何).
- 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样不管mem-initializers的顺序如何).
- 最后,执行构造函数体的复合语句.
[ 注意:声明顺序的作用是确保以初始化的相反顺序销毁基础和成员子对象.- 结束说明 ]
因此,基类在非静态数据成员之前初始化.如果代码实际上以任何方式使用未初始化的数据,则可能会调用未定义的行为.
在评论中,我们讨论了一个可能的设计问题解决方案是使用has-a而不是is-a.你担心有一个会违反DRY(不要重复自己).
在使用has-a时,有两种方法可以避免WET(写入所有内容(至少两次)).一种是使用转换运算符,允许将对象传递给期望"派生"类型的函数.另一个是使用委托运营商.
class Object { /* ... */ };
class FakeDerivedObject {
Foo foo;
Object obj;
//...
// conversions
operator Object & () { return obj; }
operator const Object & () const { return obj; }
operator Object * () { return &obj; }
operator const Object * () const { return &obj; }
// delegation
Object * operator -> () { return &obj; }
const Object * operator -> () const { return &obj; }
};
Run Code Online (Sandbox Code Playgroud)
这样,您就不必"重新实现"底层对象的接口.
FakeDerivedObject d;
d->SomeMethodOfUnderlyingObject();
SomeFunctionThatExpectsUnderlyingObject(d);
Run Code Online (Sandbox Code Playgroud)