c++ - 为什么基类指针指向基类中的纯虚方法而不是派生类中的重写方法?

标签 c++ inheritance gcc run-time-polymorphism

#include <iostream>

class A
{
    public:
        virtual ~A() = default;
        virtual void foo(void) = 0;
};

class B : public A
{
    private:
        int x;

    public:
        B(int a) : x(a) {}
        void foo(void) { std::cout << "B: " << x << "\n"; }
};

class Foo
{
    private:
        A* a_ptr;

    public:
        Foo (B& x) { a_ptr = &x; }
        A* get_ptr(void) { return a_ptr; }
        void dummy(void) { std::cout << "Foo: "; std::cout << a_ptr << "\t "<< typeid(*a_ptr).name() << "\n"; a_ptr->foo(); std::cout << "\n"; }
};

int main(void)
{
        B b(10);
        Foo f(b);

        f.dummy();
        return 0;
}
如果Foo的构造函数引用了B的对象,则此程序将执行我期望的方式,即a_ptr->foo()调用B::foo()
但是,如果将构造函数更改为按值接受参数,则a_ptr->foo()解析为A::foo(),并生成pure virtual method called exception样本输出(通过引用:):
Foo: 0x7fffe90a24e0      1B
B: 10

样本输出(按值传递):
Foo: 0x7fffc6bbab20      1A
pure virtual method called
terminate called without an active exception
Aborted (core dumped)

对于为什么会发生这种情况,我有一个模糊的预感,我正在寻找一些可以证明或反驳我的假设的文献或引用:当通过引用传递时,基类指针a_ptr指向一个生命周期超过过去的实体调用a_ptr->foo()
但是,当按值传递时,a_ptr指向一个临时变量,该临时变量在构造函数退出时丢失。
我想这与VTABLEA有关,但是我不能完全依靠它。

最佳答案

是的,您的怀疑是正确的。
B对象按值传递给Foo构造函数时,它成为该构造函数的局部变量。构造函数正在保存指向该本地对象的指针,该指针在构造函数退出时会超出范围。
因此,在a_ptr->foo()中对Foo::dummy()的调用实际上是未定义的行为,因为a_ptr甚至都没有指向有效的对象。但是,它并没有真正崩溃,因为A::foo()不使用this指针进行任何操作。它只是指向编译器定义的函数,该函数会引发pure virtual method called错误,但您不会捕获该错误,因此程序将终止。

关于c++ - 为什么基类指针指向基类中的纯虚方法而不是派生类中的重写方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63291546/

相关文章:

c++ - 通过 mex 使用 matlab 运行 opencv 代码失败,而在 VisualStudio 上它可以工作

c++ - 如何将 std::pair 视为两个单独的变量?

java - 如何使用继承的实体对 REST API 进行建模?

c - 如何编写一小段内联 gnu 扩展程序集来交换两个整数变量的值?

c++ - 在 C++/G++ 中是否有*任何*方法来获取 C 样式数组的长度?

c++ - 将结构数组传递给函数并通过函数更改它

c++ - C++中的字符串反转

python - 跳过父类(super class) __init__ 的一部分?

Java - java.lang.NoSuchMethodException

c - 带有相应标志的 "c99"和 "gcc"命令有什么区别?