C++ 经过一些处理后,如何调用父构造函数?

C++ 经过一些处理后,如何调用父构造函数?,c++,C++,我想在调用父构造函数之前进行一些处理。下面的例子说明了为什么我想这样做,尽管为了清楚起见,我已经把它稍微简化了一点。真正的父构造函数正在进行一些渲染,但是让我们先尝试解决这个问题 本质上,当父构造函数调用重写函数,但子构造函数的数据尚未设置时,问题就出现了。我该如何解决这个问题 class BaseClass { public: int myNumber; BaseClass(){ myNumber = 0; this->printNumber

我想在调用父构造函数之前进行一些处理。下面的例子说明了为什么我想这样做,尽管为了清楚起见,我已经把它稍微简化了一点。真正的父构造函数正在进行一些渲染,但是让我们先尝试解决这个问题

本质上,当父构造函数调用重写函数,但子构造函数的数据尚未设置时,问题就出现了。我该如何解决这个问题

class BaseClass {

public:
    int myNumber;

    BaseClass(){
        myNumber = 0;
        this->printNumber();
    }

    virtual void printNumber(){
        printf("My number is %d\n", this->myNumber);
    }
}

class ChildClass : BaseClass {

public:
    float childNumber;

    ChildClass(float myNumber) : BaseClass() {
        this->childNumber = myNumber;
    }

    void printNumber(){
        printf("My number is %f\n", this->childNumber);
    }

}

当父构造函数调用重写函数时会出现问题

不,那永远不会发生。在
BaseClass
的构造函数中,它的动态类型也是
BaseClass
,因此
printNumber()
调用将解析为它自己的编号,而不是某个派生类。为什么?因为那时
ChildClass
的构造函数还没有完成运行,所以它还没有被创建


正如@FredLarson所评论的,这里有关于这个主题的更多信息:

就像上面其他人所说的,你不应该从构造函数调用虚拟成员。但为了解决您的问题,有一个成语可能会对您有所帮助,它叫base from member:

它的基本功能是利用基类按声明顺序初始化的事实。在初始化基类之前,您可以在单独的基类中执行需要执行的操作

class OtherBaseClass {
    int Num;
    OtherBaseclass(float num) : Num(num)
    {
        printf("My number is %d\n", this->Num);
    }
};


class ChildClass : OtherBaseClass, BaseClass {

public:
    float childNumber;

    ChildClass(float myNumber) : OtherBaseClass(myNumber), BaseClass() {
....

请注意,基类的构造函数无法调用派生类的虚拟函数版本,即不会调用
ChildClass::printNumber()
function

也就是说,如果您想在基类的构造函数之前执行某些操作,一种方法是使用另一个基类,并将其置于另一个基类之前:

class RunMeFirst
{
    public RunMeFirst()
    { printf("whatever...\n"); }
};

class ChildClass : private RunMeFirst, public BaseClass 
{ /*...*/ };

在基类的构造函数之前运行以下几项:

  • 参数初始化
  • 虚拟基类的构造函数
  • 早期的构造函数声明的其他基类

一种常用的解决方案称为“来自成员的基本习惯用法”,它涉及将成员移动到首先构造的新基类。

是否必须在基类中实现呈现功能?你能不能用合成代替继承。使用组合将允许您轻松控制成员初始化顺序,例如:

#include <iostream>

class renderer
{
public:

    renderer(int number)
    {
        std::cout << "Number is " << number << std::endl;
    }
};

class foo
{
public:

    foo()
        : number_(12)
        , renderer_(number_)
    {
    }

private:

    int number_;
    renderer renderer_;

};

int main()
{
    foo bar;
}
#包括
类渲染器
{
公众:
渲染器(整数)
{

std::cout感谢@K-ballo指出了错误,正因为如此,我才能够稍微重新构造代码来做我想做的事情,但由于这也不是问题的技术正确答案,我将保留正确答案

class BaseClass {

public:
    int myNumber;

    BaseClass(bool initialize = true){
        myNumber = 0;
        if (initialize){
            this->initialize();
        }
    }

    void initialize(){
        this->printNumber();
    }

    virtual void printNumber(){
        printf("My number is %d\n", this->myNumber);
    }
}

class ChildClass : BaseClass {

public:
    float childNumber;

    ChildClass(float myNumber) : BaseClass(false) {
        this->childNumber = myNumber;
        this->initialize();
    }

    void printNumber(){
        printf("My number is %f\n", this->childNumber);
    }

}

更多信息:+1感谢您指出我假设中的错误。然而,这并不是标题中所述问题的答案,因此我将此标记为“答案”会感到很遗憾。+1,但请注意,这个具体的答案指出,
printNumber()如果从基类构造函数调用,基类中的
将从基类实现中调用。在本例中,这肯定是正确的,因此为+1。但是,如果您的
memberFn()
在基类中是纯虚拟的。下面是上述习惯用法的一个增强实现:您可以从构造函数调用虚拟函数。