问题描述
我正在阅读 , 项目9:在构造或销毁过程中切勿调用虚拟函数。而且我想知道我的代码是否违反了此规则也可以正常使用:
I'm reading Effective C++, and there is the "Item 9: Never call virtual functions during construction or destruction". And I'm wondering if my code is fine even if it breaks this rule:
using namespace std;
class A{
public:
A(bool doLog){
if(doLog)
log();
}
virtual void log(){
cout << "logging A\n";
}
};
class B: public A{
public:
B(bool doLog) : A(false){
if(doLog)
log();
}
virtual void log(){
cout << "logging B\n";
}
};
int main() {
A a(true);
B b(true);
}
此方法是否有问题?当我做一些更复杂的事情时,我可能会遇到麻烦吗?
Is there something wrong with this approach? May I get in trouble when I do something more complicated?
对我来说,大多数答案都没有我所做的那样,他们只是在再次解释为什么
It seams to me that most answers didn't get what I did there, and they simply explained again why is calling virtual function from constructor potentially dangerous.
我想强调一下程序的输出如下:
I would like to stress out that output of my program looks like this:
logging A
logging B
构造时我得到A记录,构造时得到B记录。这就是我想要!但是,我要问您是否发现 hack有什么错误(潜在危险),以克服在构造函数中调用虚拟函数的问题。
So I get A logged when it is constructed and B logged when it is constructed. And that is what I want! But I'm asking if You find anything wrong(potentially dangerous) with my "hack" to overcome the problem with calling virtual function in constructor.
推荐答案
这取决于您所说的好。您的程序格式正确,行为明确,因此不会调用未定义的行为或类似的东西。
It depends on what you mean by "fine". Your program is well-formed, and its behavior is well-defined, so it won't invoke undefined behavior and stuff like that.
但是,当看到对虚拟函数的调用,则可以通过调用由覆盖该函数的最派生类型提供的实现来解决该调用。
However, one may expect, when seeing a call to a virtual function, that the call is resolved by invoking the implementation provided by the most derived type which overrides that function.
除了在构造过程中,尚未构造相应的子对象外,因此派生最多的子对象是当前正在构造的子对象。结果:调度呼叫,就好像该函数不是虚拟的一样。
Except that during construction, the corresponding sub-object has not been constructed yet, so the most derived subobject is the one currently being constructed. Result: the call is dispatched as if the function were not virtual.
这是违反直觉的,您的程序不应依赖此行为。因此,作为一名有文化的程序员,您应该习惯于避免这种模式,并遵循Scott Meyer的指南。
This is counter-intuitive, and your program should not rely on this behavior. Therefore, as a literate programmer, you should get used to avoid such a pattern and follow Scott Meyer's guideline.
这篇关于从构造函数调用虚函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!