5

我有一个这样定义的纯虚拟类:

class BaseClass {
 protected:
  const int var;
 public:
  void somefun() = 0; // what I mean by a purely virtual class
  // stuff...
};

如果我不添加这样定义的构造函数:

BaseClass(const int & VAR) : var(VAR) {};

我必须随后在派生类中使用,我的派生类无法将 const 变量 var 初始化为它想要的任何值。现在我真的明白这里发生了什么。在构造派生类之前,调用基类的构造函数,此时必须初始化 const 成员变量。我的问题不是“我如何让我的代码工作”之类的问题,这已经完成了。我的问题是关于为什么编译器认为它是必要的。对于一个纯粹的虚拟课程,我不应该被允许写这样的东西:

class DerivedClass : BaseClass {
 public:
  DerivedClass() : var(SOME_VALUE) {};
}

如果编译器知道调用 BaseClass 构造函数之后必然会调用一些派生类构造函数(因为抽象类型的对象永远不能被实例化),它不应该给我们更多的余地吗?

这都是 C++ 选择绕过 Diamond 问题的结果吗?即使是这样,编译器不应该至少以某种方式允许纯虚函数的 const 成员变量将在派生类中定义的可能性吗?是不是太复杂了,或者这是否与钻石问题的 C++ 解决方案相混淆?

感谢大家的帮助。

4

3 回答 3

6

它不是“纯虚拟的”(不管你是什么意思)——它包含一个数据成员。

类成员只能由该类的构造函数的初始化列表初始化,而不是派生类的初始化列表。这就是指定对象初始化的方式:所有被初始化的成员,在构造函数体开始之前被初始化。

常量对象必须被初始化,因为它们以后不能被赋值。

因此,具有常量数据成员的类必须在每个构造函数中对其进行初始化。

于 2012-02-22T17:03:42.417 回答
2

对于一个纯粹的虚拟课程,我不应该被允许写类似的东西吗

不,但是您可以(并且在这种情况下应该)编写如下内容:

class DerivedClass : BaseClass {
 public:
  DerivedClass() : BaseClass(SOME_VALUE) {};
};
于 2012-02-22T17:04:19.777 回答
2

对象的构造以特定的顺序发生。在运行派生类的构造函数之前,必须完全构造基类,以便派生构造函数使用完全形成且有效的基对象。如果基成员变量的初始化被推迟到派生类的构造,这个不变量就会被破坏。

于 2012-02-22T17:21:36.913 回答