Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以调用虚函数来初始化基类子对象吗?_C++_Constructor_Virtual_Ctor Initializer - Fatal编程技术网

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
};