You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在无指针/引用的情况下实现C++多态调用派生类方法

问题:如何通过Base类对象调用Child类的虚函数实现?

我定义了基类Base和继承它的派生类Child,Base中声明了一个virtual成员函数,Child重写了该函数。我想声明一个Base类对象,用Child的构造函数初始化它,然后调用Child版本的成员函数。以下是我的代码:

#include <iostream>

class Base {
public:
    virtual int give_number(int x) { return x; }
};

class Child : public Base {
public:
    int give_number(int x) { return x+1; }
};

int main() {
    Base base;
    Child child;
    Base child2;
    child2 = Child();
    std::cout << "Base says " << base.give_number(1) << "\n";
    std::cout << "Child says " << child.give_number(1) << "\n";
    std::cout << "Child2 says " << child2.give_number(1) << "\n";
}

这段代码的实际输出是:

Base says 1
Child says 2
Child2 says 1

但我期望的输出是:

Base says 1
Child says 2
Child2 says 2

请问有没有办法实现这个需求?


解答

这是对象切片导致的问题:当你把Child对象赋值给Base对象时,Child中属于派生类的额外信息会被“切掉”,最终child2只是一个纯粹的Base对象,调用虚函数时自然只会执行Base的版本。

要实现你的需求,不能直接用基类对象存储派生类实例,必须借助指针或引用来触发虚函数的多态性:

方案1:使用基类指针

通过基类指针指向派生类对象,这样不会发生切片,调用虚函数时会根据实际对象类型执行对应版本:

#include <iostream>

class Base {
public:
    virtual int give_number(int x) { return x; }
};

class Child : public Base {
public:
    int give_number(int x) { return x+1; }
};

int main() {
    Base base;
    Child child;
    Base* child2 = new Child(); // 基类指针指向派生类实例
    std::cout << "Base says " << base.give_number(1) << "\n";
    std::cout << "Child says " << child.give_number(1) << "\n";
    std::cout << "Child2 says " << child2->give_number(1) << "\n";
    delete child2; // 手动释放堆内存,避免泄漏
}

方案2:使用基类引用

引用必须在声明时初始化,不能像对象那样后续赋值,通过基类引用绑定到派生类对象,同样能触发多态:

#include <iostream>

class Base {
public:
    virtual int give_number(int x) { return x; }
};

class Child : public Base {
public:
    int give_number(int x) { return x+1; }
};

int main() {
    Base base;
    Child child;
    Child child_obj;
    Base& child2 = child_obj; // 基类引用绑定到派生类对象
    std::cout << "Base says " << base.give_number(1) << "\n";
    std::cout << "Child says " << child.give_number(1) << "\n";
    std::cout << "Child2 says " << child2.give_number(1) << "\n";
}

如果想绑定临时对象,可以使用const引用:

const Base& child2 = Child();

核心原因

C++的虚函数多态性只有通过指针或引用才能生效,因为它们保存的是实际对象的地址/绑定关系,不会丢失派生类的类型信息。而直接赋值基类对象会发生切片,只保留基类部分,自然无法触发派生类的虚函数实现。


内容的提问来源于stack exchange,提问作者duckmayr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 18:25:21