【问题标题】:Initialize member before base constructor. Possible? [duplicate]在基本构造函数之前初始化成员。可能的? [复制]
【发布时间】:2015-06-19 15:39:40
【问题描述】:

我有以下代码:

class A{
public:
    A(int* i){
        std::cout << "in A()" << i << std::endl;
    }
};

class B: public A{
public:
    B(): i{new int{10}}, A{i}{
        std::cout << "in B()" << std::endl; 
    }

private:
    int* i;
};

int main()
{
    B b;
}

A 构造函数中,我有 0(这是预期的)。但我想在之前初始化i。有可能吗?

【问题讨论】:

  • 不清楚您要完成什么。但是,就在我的脑海中:A 的构造函数以及在其中执行的任何初始化都将始终在调用 B 的构造函数之前执行。强制初始化首先在 B() 中发生的唯一方法是在其中声明 A 没有的成员。即使这样,所有继承的成员都将首先在 A() 中初始化。您为什么不告诉我们您为什么要这样做,也许我们可以提供帮助。
  • 这就像在创造头骨之前要求上帝在头骨中为你的眼睛创造眼窝
  • 你不能在基类之前初始化成员,但是你可以通过添加一个基类来近似它来保存你想要提前初始化的成员。基类按顺序初始化。 godbolt.org/g/puv6T5struct Bi_ { int* i; }; class B : private Bi_, public A {...};
  • 问题已结束。所以,在这里尝试回答:我遇到了同样的问题并通过不使用继承而是将A作为成员放入B来解决它:class A { /* base */ };class B { int *i; A a; ... B() : i{...}, A{...} { } };(注意顺序B 成员 - i) 之后的 a。当然,这只有在 A 不是抽象的并且继承不是强制性的情况下才有可能——在我的情况下两者都是正确的。您还可以在 B 中添加一个转换运算符以转换为 A。您的情况如下所示:A 仅包含一个引用,B 应该从该引用中分配和构造 A。所以,也许它也适合你的情况。

标签: c++


【解决方案1】:

i 是类B 的数据成员,所以为了创建,必须首先创建类B 的对象。所以答案是否定的。

【讨论】:

  • 不过有办法。你可以这样做:B(): A{i = new int{10}}{ std::cout &lt;&lt; "in B()" &lt;&lt; std::endl; }
【解决方案2】:

不,这是不可能的,因为基类初始化总是在派生类初始化之前。

C++11、12.6.2

10 在非委托构造函数中,初始化按以下顺序进行:

  • 首先,并且仅对于最派生类 (1.8) 的构造函数,虚拟基类按照它们在基类的有向无环图的深度优先从左到右遍历中出现的顺序进行初始化,其中“从左到右”是派生类基类说明符列表中基类的出现顺序。

  • 然后,直接基类按照它们出现在 base-specifier-list 中的声明顺序进行初始化(不管 mem-initializers 的顺序如何)。

  • 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样与 mem-initializers 的顺序无关)。

  • 最后,构造函数体的复合语句被执行。

【讨论】:

    【解决方案3】:

    在基本构造函数之前初始化成员。可能吗?

    不,这是不可能的。该标准要求在初始化类的成员之前首先初始化基类。

    B(): i{new int{10}}, A{i}{
        std::cout << "in B()" << std::endl; 
    }
    

    转化为:

    B(): A{i}, i{new int{10}}{
        std::cout << "in B()" << std::endl; 
    }
    

    【讨论】:

      猜你喜欢
      • 2021-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多