C++调用派生类中覆盖的基类函数

3

我有两个类,AB,我需要在A的构造函数中调用B中被重写的函数。以下是我的代码:

class A {
    A(char* str) {
        this->foo();
    }

    virtual void foo(){}
}

class B : public A {
    B(char* str) : A(str) {}

    void foo(){
        //stuff here isn't being called
    }
}

我该如何在 A::A() 中调用 B::foo() 方法的代码?

2
不要在构造函数中使用虚函数。当正在构造B时,A会首先被构造。此时,B的额外方法/变量还没有设置好。因此,事情可能会出现严重问题。 - Ed Heal
3个回答

3

很遗憾,这对我来说行不通,不过还是很有趣的,谢谢。 - MPenate
请问您能解释一下为什么吗?也许我可以帮忙。 - Piotr Smaroń
对我来说,这是一个特殊情况。我在基类中有一个特定的构造函数,大致如下:初始化变量->创建对象->运行循环。我试图使用的函数是创建对象。因此,我将我的基类翻转过来,现在有两个函数init()start(),在这两个函数之间,我调用了makeObjects()函数。 - MPenate

3

我需要在B中创建一个重载函数,并从A的构造函数中调用它

在C++中,这种设计是不可能的:B对象的构造顺序是首先构造基类A子对象,然后在其之上构造B。

因此,在A的构造函数中,您仍在构造一个A对象:此时调用任何虚函数都将是A的虚函数。只有当A构造完成并开始B构造时,B的虚函数才会生效。

要实现您想要的功能,您必须使用两步模式:1)构造对象,2)初始化对象。


很好。我认为这里需要一个好的进一步说明,也解释了为什么这是C++的设计;也就是说,假设虚函数的内容和期望(例如,某些成员已经初始化)是危险的。 - Yam Marcovic
@YamMarcovic, 基于首先构建逻辑的合理性是由Bjarne Stroustrup在《C++设计与演化》第283页中解释的:如果覆盖的函数在构造期间被调用,它将不知道哪些成员已经构建,每个覆盖的函数都必须小心翼翼地编写,对于构造函数来说这是非常必要的。 - Christophe
1
这正是我想表达的意思 - 如果不够清晰,对不起。我认为在回答中提到它会是一个很好的补充。 - Yam Marcovic

1
在构造函数中,将调用基类的函数,而不是被重写的版本。原因是,在您的示例中,当调用A的构造函数时,B的初始化尚未完成,因此如果允许这样做,则使用不完整的B实例调用B的foo。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接