虚拟功能分割故障

问题描述

我想学习虚函数。我在Base类虚拟中创建了print(),程序崩溃了。为什么必须用new创建两个对象?

#include <iostream>

class Base {
    public:
        virtual void print();
};

void Base::print() {
    std::cout << "Base print method" << std::endl;
}

class Derived : public Base {
    public:
        void print();
};

void Derived::print() {
    std::cout << "Derived print method" << std::endl;
}

int main()
{
    Base* b; // Base* b = new Base(); runs
    b->print();
    Derived* d; // Derived *d = new Derived(); runs
    d->print();
}

解决方法

为什么必须用new创建两个对象?

您不必。

一个常见的误解是您需要动态创建用于多态的对象。通常将多态用于动态创建的对象,但严格启用多态并不是必需的。您需要多态性的引用或指针,因此例如,它将起作用:

#include <iostream>

class Base {
    public:
        virtual void print();
};

void Base::print() {
    std::cout << "Base print method" << std::endl;
}

class Derived : public Base {
    public:
        void print();
};

void Derived::print() {
    std::cout << "Derived print method" << std::endl;
}

void do_print(Base& b) {
   b.print();
}    

int main()
{
    Base b;
    do_print(b);
    Derived d;
    do_print(d);
}

在您的代码中,main中仅包含指针,但从未创建对象。您的指针不指向对象,它们未初始化,因此完全没有用。取消引用这些指针会调用未定义的行为。

,

因为Base* b不会创建对象,只要您不通过添加new Base()来告诉它这样做。因此,取消引用print函数的指针没有有效的目标。

,

Base* b;不会创建对象,而是会创建具有自动存储持续时间 Base*类型的指针。取消引用该指针的行为是不确定的。

Base bnew Base()实际上创建对象。前者具有自动存储期限,后者具有动态存储期限。

,

您正在使用指针,因此它们需要指向某个东西。

您基本上是在说:“嘿,这个b变量指向Base对象”,但是您从未创建基础对象(使用new),所以它指向随机内存,当您尝试将该内存视为Base对象时会崩溃。