C++ 我可以调用虚函数来初始化基类子对象吗?
我知道不应该在构造函数中直接或间接调用虚拟函数,但这段代码运行良好。C++ 我可以调用虚函数来初始化基类子对象吗?,c++,constructor,virtual,ctor-initializer,C++,Constructor,Virtual,Ctor Initializer,我知道不应该在构造函数中直接或间接调用虚拟函数,但这段代码运行良好。 我这里的东西安全吗 #include <iostream> #include <string> struct A { A (const std::string& name) {std::cout << name << std::endl;} virtual std::string tag() const = 0; }; struct B: A {
我这里的东西安全吗
#include <iostream>
#include <string>
struct A {
A (const std::string& name) {std::cout << name << std::endl;}
virtual std::string tag() const = 0;
};
struct B: A {
B() : A (tag()) {}
virtual std::string tag() const override {return "B";}
};
int main() {
B b; // Output gives "B\n"
}
在构造函数和/或析构函数中调用虚拟成员通常是可以的 不过,在初始化所有基之前,ctor初始化器中的游戏不同: 12.6.2初始化基和成员
[class.base.init]
[…]对于正在构造的对象,可以调用14个成员函数(包括虚拟成员函数,10.3)。 类似地,正在构造的对象可以是
typeid
运算符(5.2.8)或动态转换(5.2.7)的操作数。但是,如果在基类的所有mem初始值设定项完成之前,这些操作在ctor初始值设定项中执行(或在直接或间接从ctor初始值设定项调用的函数中执行),则操作结果未定义。
“我知道虚拟函数不应该在构造函数中直接或间接调用”。。。这是一个新的…@重复数据消除器。根据你的评论,我在上面写了一个不同的版本。这就是你的建议吗?@Deduplicator什么时候开始的@LightnessRacesinOrbit:恢复并扩展注释:在ctor初始值设定项中调用虚拟函数是非常必要的,因为标准在12.6.2(14)中有这样的规定。@Deduplicator Touché。具体来说,这只是因为基尚未完成初始化。好的,这说服我使用您的静态函数重定向建议进行第二次设计。@prestokeys:是的,直接调用静态函数。最后一句话不就是指typeid和dynamic\u cast吗?以及如何在基类的mem初始值设定项之前执行ctor初始值设定项?@EJP:MyClass():MyBase(dynamic_cast(this)){}
和类似命令。@EJP:如果在ctor初始值设定项列表中显式指定基类初始值设定项,则可以执行该命令。例如,与OP的原始代码样本完全相同。由于虚拟函数调用tag()
用作基类初始值设定项的参数(在ctor初始值设定项列表中),因此必须在基类初始值设定项有机会完成之前调用此虚拟函数。这可能正是上面引用的意思。
// Replacement for class B:
struct B: A {
B() : A (name()) {}
virtual std::string tag() const override {return name();}
private:
static std::string name() {return "B";} // use static function
};