加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在父类之前构造C成员类吗?

发布时间:2020-12-16 09:53:43 所属栏目:百科 来源:网络整理
导读:参见英文答案 C++: Construction and initialization order guarantees????????????????????????????????????5个 在场景中: class A : public B {private: C m_C; public: A();} 是 A::A() : m_C(5),B(m_C) {} 法律?在C :: C(int)之后会调用B :: B(m_C)吗
参见英文答案 > C++: Construction and initialization order guarantees????????????????????????????????????5个
在场景中:

class A : public B {
private:
   C m_C; 
public:
   A();
}

A::A() : 
   m_C(5),B(m_C) 
{}

法律?在C :: C(int)之后会调用B :: B(m_C)吗?如果是这样,我该怎么办才能避免呢?

这是如何实现的:

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. 
}

我已经发现了

const QRegExp & QRegExpValidator::regExp() const;

这减轻了我自己对myRegExp的引用的需要,所以我的特定问题就解决了..

剩下的是,如果QRegExpValidator没有这样的功能来检索它的初始化程序,那么最好的模式是什么?手动将所有函数传递给成员类,而不是继承?

解决方法

这就是C 11标准所说的([class.base.init] / 10):

In a non-delegating constructor,initialization proceeds in the following order:
— First,and only for the constructor of the most derived class (1.8),virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes,where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
— Then,direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
— Then,non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
— Finally,the compound-statement of the constructor body is executed.
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. — end note ]

因此,基类在非静态数据成员之前初始化.如果代码实际上以任何方式使用未初始化的数据,则可能会调用未定义的行为.

在评论中,我们讨论了一个可能的解决方案,你的设计问题是使用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; }
};

这样,您就不必“重新实现”底层对象的接口.

FakeDerivedObject d;

d->SomeMethodOfUnderlyingObject();
SomeFunctionThatExpectsUnderlyingObject(d);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读