|
|
1
39
(这个答案适用于C++和java。我相信C++在这方面的工作方式不同。) 在构造函数中调用虚方法确实是危险的,但有时它会以最干净的代码结束。 极大地 做 在构造函数中使用虚拟方法,并将其记录下来 强烈地只要所有参与的人都知道它在做什么,就不应该导致 也 很多问题。不过,我会尽量限制可见性,正如您在第一个示例中所做的那样。
在哪里
|
|
|
2
10
在C++中,调用基类构造函数中的虚拟方法将简单地调用该方法,就好像派生类还不存在(因为它不存在)。这意味着调用在编译时被解析为它应该在基类(或它派生的类)中调用的任何方法。 通过GCC测试,它允许您从构造函数调用纯虚拟函数,但它会发出警告,并导致链接时间错误。该行为似乎未被标准定义: 成员函数可以从抽象类的构造函数(或析构函数)调用;进行虚拟调用的效果( )对于从此类构造函数(或析构函数)创建(或销毁)的对象,直接或间接向纯虚函数的调用是未定义的。” |
|
|
3
4
使用C++,虚拟方法通过VTABLE路由到正在构建的类。因此,在您的示例中,它将生成一个纯虚拟方法异常,因为在构造BaseObject时,根本没有LoadStateCore方法可调用。 如果函数不是抽象的,而只是什么都不做,那么您经常会让程序员挠头,试图记住为什么函数实际上没有被调用。 因为这个原因,你不能用C++的方式来做… |
|
|
4
4
对于C++,在派生构造函数之前调用基本构造函数,这意味着虚表(它包含派生类的重写虚函数的地址)还不存在。因此,这被认为是一件非常危险的事情(特别是如果函数在基类中是纯虚拟的……这将导致纯虚拟异常)。
(1)的一个例子是:
方法(2)使用工厂模式为
|
|
|
5
3
对于C++,第12.7节第3段的标准涵盖了这种情况。
总而言之,这是合法的。它将根据正在运行的构造函数的类型解析为正确的函数。因此,将您的示例应用到C++语法中,您将调用
第10.4节第6段介绍了抽象类的构造函数。简言之,它们可以调用成员函数,但在构造函数中调用纯虚函数是未定义的行为。不要那样做。 |
|
6
3
如果您有一个类,如您的帖子所示,它需要
这样,您的代码就非常简单,并且您没有任何虚拟方法调用问题。 |
|
|
7
3
Never Call Virtual Functions during Construction or Destruction 注:请注意本文中的例外情况:
|
|
8
1
通常,您可以通过使用更贪婪的基本构造函数来解决这些问题。在您的示例中,将XElement传递给LoadState。如果允许在基本构造函数中直接设置状态,则子类可以在调用构造函数之前解析XElement。
如果子类需要做大量的工作,它可以转移到静态方法。 |
|
9
1
在C++中,从基类中调用虚拟函数是完全安全的,只要它们是
非纯
调用的版本是从构造函数中调用它的类的版本,而不是某个派生类中的某个重写器。这与虚拟函数表没有多大关系,但更重要的是,该函数的重写可能属于尚未初始化的类。所以这是禁止的。 在C#和Java中,这不是问题,因为没有在进入构造函数主体之前完成的默认初始化。在C#中,唯一在主体之外完成的事情是调用基类或兄弟构造函数,我相信。但是,在C++中,当在进入派生类的构造函数体之前处理构造函数初始化列表时,在函数的重写器中对派生类成员进行初始化时,将不进行初始化。 编辑 :由于有评论,我认为需要澄清一下。下面是一个(人为的)示例,假设允许调用virtuals,并且调用将导致激活最终重写器:
这个问题确实可以通过改变C++标准并允许它来调整——构造函数的定义、对象生存期和不发生的事情来解决。必须制定规则来定义什么
|
|
KiraHoneybee · 具有构造函数参数的模板化类 4 年前 |
|
|
nick2225 · 隐式调用复制构造函数? 4 年前 |
|
|
nohaga · 为什么在本例中p3需要默认构造函数? 4 年前 |
|
|
Aadil Hoda · 为什么类类型的成员需要初始化? 4 年前 |
|
|
EloiGG · 具有任意类型的变量的可数的C++函数 4 年前 |