C++ 在派生类对象构造后调用虚函数

C++ 在派生类对象构造后调用虚函数,c++,constructor,polymorphism,C++,Constructor,Polymorphism,以下是一些示例代码: #include <iostream> class A { public: virtual void foo() { std::cout << "base" << std::endl; } A() { foo(); } }; class B : public A { int a; public: void foo() { std::cou

以下是一些示例代码:

#include <iostream>

class A {
public:
    virtual void foo() {
        std::cout << "base" << std::endl;
    }

    A() {
        foo();
    }
};

class B : public A {
    int a;
public:
    void foo() {
        std::cout << "derived" << std::endl;
    }

    B(int a) :
        a(a) {}
};

int main() {
    B o(1);
    return 0;
}
#包括
甲级{
公众:
虚拟void foo(){

std::cout无法调用重写的
foo()
从基类构造函数开始,无论您做什么。调用基类构造函数时,派生类对象尚未构造,因此您无法调用其任何方法或访问其任何成员。对于虚拟函数和常规函数也是如此。在基类构造函数中ode>此
指针指向基类,而不是派生类。

无法调用重写的
foo()
从基类构造函数开始,无论您做什么。调用基类构造函数时,派生类对象尚未构造,因此您无法调用其任何方法或访问其任何成员。对于虚拟函数和常规函数也是如此。在基类构造函数中ode>此指针指向基类,而不是派生类。

一个潜在的解决方法是将构造委托给客户端必须调用的单独函数。然后让该函数在构造后调用foo:

class A {
public:
    virtual void foo() {
        std::cout << "base" << std::endl;
    }

    template<typename T, typename ... Args>
    static T construct(Args ... args)
    {
        T newT{ args... };
        newT.foo();
        return std::move(newT);
    }

protected:
    A() {
        //Construct A
    }
};
class B : public A {
    int a;
public:
    void foo() {
        std::cout << "derived" << std::endl;
    }

    B(int a) :
        a(a) {}
};

int main()
{
    B o = A::construct<B>(1);
    A a = A::construct<A>();
    return 0;
}
A类{
公众:
虚拟void foo(){

std::cout一个潜在的解决方法是将构造委托给客户端必须调用的单独函数。然后让该函数在构造后调用foo:

class A {
public:
    virtual void foo() {
        std::cout << "base" << std::endl;
    }

    template<typename T, typename ... Args>
    static T construct(Args ... args)
    {
        T newT{ args... };
        newT.foo();
        return std::move(newT);
    }

protected:
    A() {
        //Construct A
    }
};
class B : public A {
    int a;
public:
    void foo() {
        std::cout << "derived" << std::endl;
    }

    B(int a) :
        a(a) {}
};

int main()
{
    B o = A::construct<B>(1);
    A a = A::construct<A>();
    return 0;
}
A类{
公众:
虚拟void foo(){

std::cout To clear,您希望调用派生的
foo()
重载,即使这不是示例程序中发生的情况?是的。如果重载会发生在我的代码中,那么我的问题是没有意义的。Oops,我的意思是重写,而不是重载。要明确,您希望派生的
foo()
要调用的重载,即使在示例程序中不是这样的情况?是的。如果重载会发生在我的代码中,那么我的问题就没有意义了。哦,我的意思是重写,而不是重载。我不需要从构造函数调用它。我想在所有派生类对象构造(完整)之后调用它,但不需要在派生类中添加其他代码。@Omicrons,很抱歉,这是不可能的。@Omicrons这也非常令人困惑,您想从派生类调用函数而不向派生类添加额外代码吗?当然,从派生类调用任何函数的实现都会导致n额外代码?为什么不让派生类调用基类要调用的任何函数?我不需要从构造函数调用它。我想在所有派生类对象构造(完整)之后调用它,但不需要在派生类中添加其他代码。@Omicrons,很抱歉,这是不可能的。@Omicrons这也非常令人困惑,您想从派生类调用函数而不向派生类添加额外代码吗?当然,从派生类调用任何函数的实现都会导致n额外的代码?为什么不让派生类调用基类将要调用的任何函数?问题是,您仍然可以执行
bo(1);
-因此需要程序员规范来使用创建者。但是如果您有足够的规范来使用创建者,为什么还要麻烦它呢?根据相同的规范,您可以简单地调用foo()在调用站点。@SergeyA Yup,这并不完美。您可以使子类构造函数也受到保护,但是您需要在所有子类中声明友元。在这种情况下,这可能是合理的。我仍然认为这是OP问题的合理解决方案。问题是您仍然可以执行
BO(1)
-所以使用creator需要程序员的纪律。但是如果你有足够的纪律来使用creator,为什么还要麻烦它呢?根据同样的纪律,你可以简单地调用foo()在调用站点。@SergeyA Yup,这并不完美。您可以使子类构造函数也受到保护,但是您需要在所有子类中声明友元。在这种情况下,这可能是合理的。我仍然认为这是解决OP问题的合理方法。