成员列表初始化与继承?

Posted

技术标签:

【中文标题】成员列表初始化与继承?【英文标题】:Member list initialization with inheritance? 【发布时间】:2021-04-01 18:32:18 【问题描述】:

我想为 C 类构建一个构造函数,如最后一行所示。我不明白为什么它不起作用。如果我删除 :B(b, A bb):b(b), bb(bb) 很好,但是我不能为 b 和 bb 提供值。另外,我不确定如何在主函数中创建一个包含所有参数的对象。

class A

protected:
   int a, aa;
public:
   A();
   A(int a, int aa);
   ~A();
   friend class B;
   friend class C;
;
class B

protected:
   int b;
   A bb;
public:
   B();
   B(int b, A bb);
   ~B();
;
class C: class B

private:
   int c;
   A cc;
public:
   C();
   C(int c, A cc);
   ~C();
  ;

C:C(int c, A cc):c(c), cc(cc):B(b, A bb):b(b), bb(bb)  // I tried smth like this, but obviously it doesn't work

int main()

 A aaa(1, 2);
C(3, A); ///how can i set values for B-members

【问题讨论】:

您写的内容无效。您需要将变量传递给B 的构造函数:即:C::C(int c, A cc) : B(c, cc), c(c), cc(cc) 。 PS:真心推荐更好的变量名。 A(int b, A bb);class B 中毫无意义。而B(b, A bb) 在成员初始化列表中当然没有任何意义。 【参考方案1】:

首先,C对B的继承被破坏了,它需要class C: B,而不是class C: class B。所以你甚至在它到达初始化列表之前就遇到了编译器错误。您不能指望我们修复您的代码不是您的问题的一部分...

但重点是:请记住,当您构造 B 类的子类 C 的实例时,您应该首先构造 B 实例。这也适用于初始化列表。所以构造函数必须是这样的:

C::C(/* whatever */) : B(/* whatever */), /* construction of direct members of C */  

现在,对于您的具体列表,正如@ChrisMM 建议的那样,它应该是:

C::C(int c_, A cc_) : B(c_, A cc_), c(c_), cc(cc_)  

这些是我对您的线路所做的更改:

    为了定义构造函数,我将其称为 C::C(/whatever/),并带有 两个 冒号。这是与单个冒号不同的符号 - 完全不同的含义! 先构造 B。 没有“嵌套初始化列表”之类的东西,所以您只使用一次:。 我使构造函数参数名称与字段名称不同,因为当您选择相同的名称时会非常混乱。此外,使用与类名相似但大小写不同的字段名也是一个坏主意。我知道你在这个例子中使用了这些名字,但是,这给其他人树立了一个坏榜样。

【讨论】:

【参考方案2】:

您应该做的第一件事是将您的成员变量重命名为与您的构造函数参数名称不同的名称;否则你将很难从参数中消除成员变量的歧义。

例如,在下面的代码(确实可以编译)中,我将所有成员变量重命名为具有 m_ 前缀,以使读者清楚它们是成员变量而不是其他东西。

另请注意,由B 类的构造函数设置B 对象的成员变量,因此C 类构造函数调用适当的B 类构造函数来执行此操作,而不是而不是直接设置B的成员变量。

class A

protected:
   int m_a, m_aa;

public:
   A() /* empty */
   A(int a, int aa) : m_a(a), m_aa(aa) /* empty */
   ~A() /* empty */
;

class B

protected:
   int m_b;
   A m_bb;

public:
   B() /* empty */
   B(int b, A bb) : m_b(b), m_bb(bb) /* empty */
   ~B() /* empty */
;

class C: public B

private:
   int m_c;
   A m_cc;

public:
   C() /* empty */
   C(int c, A cc);
   ~C() /* empty */
;

C::C(int c, A cc)
   : B(c, cc)
   , m_c(c)
   , m_cc(cc)

   // empty


int main()

   A aaa(1, 2);
   C ccc(3, A(4,5)); ///how can i set values for B-members

【讨论】:

以上是关于成员列表初始化与继承?的主要内容,如果未能解决你的问题,请参考以下文章

第四十六课继承中的构造与析构

C++--继承中的构造与析构父子间的冲突

继承中的构造与析构(三十九)

第46课 继承中的构造与析构

多继承 与 多重继承

C++必须使用初始化列表初始化数据成员的三种情况