重新解释为子类的父类可以在其函数中使用子类的函数吗?

Bon*_*nic 1 c++ inheritance

我想在重新解释的类中从父函数调用子函数,如下所示。

例子

#include <iostream>

class A {
public:
    void func1() {
        // some code
        func2();
        // some code
    }
protected:
    virtual void func2() {
        printf("class A\n");
    }
};

class B : public A {
protected:
    virtual void func2() {
        printf("class B\n");
    }
};

int main() {
    A* ab = new A();
    ab->func1(); // this print "class A"

    B* bab = reinterpret_cast<B*>(ab);
    bab->func1(); // this also print "class A"
    // I want to print "class B" when I use bab->func1() 
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,有没有办法使用重新解释的类来打印类 Bbab而无需重新定义func1

joe*_*ech 5

为了发挥 C++ 多态性,您必须在某处创建派生类的实例,但可以存储指向基类的指针。使用基类指针将分派到派生类的重写函数。所以你对Aand的定义B没问题,但你在 main 函数中的用法则不然。reinterpret_cast不是为此目的。

#include <iostream>
#include <memory>

class A {
public:
    void func1() {
        // some code
        func2();
        // some code
    }
protected:
    virtual void func2() {
        printf("class A\n");
    }
};

class B : public A {
protected:
    virtual void func2() {
        printf("class B\n");
    }
};

int main() {

    {
    // This works, but don't do this. Naked "new" is not modern C++ and dangerous.
    A* ab = new B();
    ab->func1();
    delete ab; 
    }

    {
    // VARIANT 2: use smart pointers
    std::unique_ptr<A> ab = std::make_unique<B>();
    ab->func1();
    }

    {
    // VARIANT 3: A non-smart pointer is okay, as long as it 
    // 1. references an existing allocated object
    // 2. the pointer does not outlive the object it points to
    B b;
    A* ab = &b;
    ab->func1();
    }

    {
    // VARIANT 4: Like Variant 3, but with reference instead of pointer
    B b;
    A& ab = b;
    ab.func1();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出

class B
class B
class B
class B
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/8e5E85nx5

编辑:尽量避免使用new. 以这种方式分配的任何内存都必须由您使用释放delete,并且很容易忘记(我第一次写这个答案时就这样做了,有点证明我的观点)。即使您确实在函数末尾删除了内存,您的代码也有可能永远不会到达此语句,例如,如果在new和 之间抛出异常delete。这里有一些进一步的阅读:

  • 为什么裸体是新的而不是现代的?为什么危险?...因为人们可能会忘记“删除”?;) (2认同)