C++ C++;使用将在派生构造函数中构造的参数调用基构造函数
问题1) 问题来了: 将对generateName()调用什么方法 问题2)C++ C++;使用将在派生构造函数中构造的参数调用基构造函数,c++,oop,class,constructor,virtual-functions,C++,Oop,Class,Constructor,Virtual Functions,问题1) 问题来了: 将对generateName()调用什么方法 问题2) 我该怎么做?如果默认构造函数必须接受参数,但我需要在派生构造函数中生成该参数?首先,解决方案是:使用静态成员函数或非成员函数 对于行为,将调用Derived::generateName()。在C++标准中定义这个行为的长句子表示(C++ 03 12.7/3): 当从构造函数(包括数据成员的mem初始值设定项)或析构函数直接或间接调用虚函数时,且调用所应用的对象是正在构造或销毁的对象,调用的函数是在构造函数或 析构函数自
我该怎么做?如果默认构造函数必须接受参数,但我需要在派生构造函数中生成该参数?首先,解决方案是:使用静态成员函数或非成员函数 对于行为,将调用
Derived::generateName()
。在C++标准中定义这个行为的长句子表示(C++ 03 12.7/3):
当从构造函数(包括数据成员的mem初始值设定项)或析构函数直接或间接调用虚函数时,且调用所应用的对象是正在构造或销毁的对象,调用的函数是在构造函数或
析构函数自己的类或在它的一个基类中,但不是在从构造函数或析构函数的类派生的类中重写它的函数,也不是在最派生的对象的其他基类中重写它的函数
因为在虚拟调用时执行的构造函数是派生的
构造函数,所以调用了派生的::generateName()
现在删除的答案正确地引用了Scott Meyers的一篇文章,该文章建议调用重写器的规则既复杂又难以记忆。拿两个例子
我在基类初始化器和两个构造函数中调用了generateName()
。结果让我不知所措:
Derived (called from Derived's Base initializer)
Base (called from Base ctor)
Derived (called from Derived ctor)
我从未想象过一个类可以在一个构造序列中从一个派生类变形为一个基类,然后再变形为一个派生类。你每天都在学习新的东西。如果从
Base::Base
内部调用generateName()
,这将是正确的。但在这里,我们在初始值设定项列表中调用它,然后再输入Base::Base
。这仍然是真的吗?啊,你已经更新了你的答案。现在感觉是这样,所以+1。@Oli:不是。我错了,在研究了这个问题并运行了一些测试之后,我已经更正了答案。事实上,我对这种特定的行为有些惊讶。我觉得不对;-)(它打破了我通常在构造过程中对虚拟函数调用进行推理的模式,现在我必须返回并找到我错误描述过程的所有答案…)感谢你质疑原始答案。我不喜欢“直接或间接来自构造函数”的说法(包括来自数据成员的mem初始值设定项)或来自析构函数的“部分”。对基构造函数的调用可以被视为“数据成员的mem初始值设定项”?我认为不是。我们甚至在构造基类之前就调用了一个虚拟函数,这感觉不太对。我用GCC对它进行了测试,并且调用了派生函数,但正如我们从另一个答案中看到的那样,有时它会断开。它不就是UB吗?@Sergey:Inderived():base(){}
,base()
是一个mem初始值设定项,虽然它不是“数据成员的mem初始值设定项”。引用的句子说“包括”,所以“数据成员的mem初始值设定项”只是一个可以从构造函数调用虚拟函数的示例。
Derived :: Derived : Base(generateName()) {
//what method will be called on generateName() ?
}
Derived (called from Derived's Base initializer)
Base (called from Base ctor)
Derived (called from Derived ctor)