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

C++通过父类list指针调用子类重载运算符实现运行时多态

问题修复方案

问题根因

代码无法触发运行时多态的核心原因有两个:

  • 运算符调用语法错误:p + (rand() % 100)是对list*类型的指针做地址算术运算,根本没有调用对象的成员运算符函数,完全不会进入虚函数分发逻辑。
  • 虚函数返回值设计缺陷:operator+定义为返回list值类型,子类重写时返回的实例会被切割为基类对象,发生对象切片,破坏多态一致性。

修复要点

  1. 修正operator+的调用逻辑:对指针解引用后再触发运算符调用,将原代码中p + (rand() % 100)替换为(*p) + (rand() % 100)。
  2. 调整operator+的返回值类型:将基类和子类中该运算符的返回值从list值类型修改为list&引用类型,避免对象切片,保证虚函数重写的合法性。

修复后完整代码

#include <iostream>
#include <cstdlib>
#include <time.h>
#include <cctype>

using namespace std;

class list
{
public:
    list* head; 
    list* tail; 
    list* next; 
    int num;
    virtual ~list() {}
    list() { head = tail = next = NULL; num = 0; }
    // 修改返回值为引用类型
    virtual list& operator+(int i) { return *this; };
    virtual int operator-() { return 0; };
};
class queue : public list
{
public:
    // 同步修改返回值为引用类型,符合虚函数重写规则
    list& operator+(int i) override;
    int operator-() override;
};

class stack : public list
{
public:
    list& operator+(int i) override;
    int operator-() override;
};

int main()
{
    srand(time(NULL)); rand();
    list* p;
    queue q_ob;
    stack s_ob;
    char ch;
    for (;;)
    {
        cout << "Enter something else to stop.\nStack, Queue or ULL? (S/Q): \n";
        cin >> ch;
        ch = tolower(ch);
        if (ch == 'q')
            p = &q_ob;
        else if (ch == 's')
            p = &s_ob;
        else break;
        // 修正:解引用指针后调用运算符
        (*p) + (rand() % 100);
    }
    cout << "Enter T to terminate\n";
    for (;;)
    {
        cout << "Remove from Stack, Queue or ULL? (S/Q):";
        cin >> ch;
        ch = tolower(ch);
        if (ch == 'q')
            p = &q_ob;
        else if (ch == 's')
            p = &s_ob;
        else break;
        cout << -(*p) << '\n';
    }
    return 0;
}

list& queue::operator+(int i)
{
    list* item;
    item = new queue;
    if (!item)
    {
        cout << "Allocation error.\n";
        exit(1);
    }
    item->num = i;
    // 队列元素追加到尾部
    if (tail)
        tail->next = item;
    tail = item;
    item->next = NULL;
    if (!head)
        head = tail;
    return *this;
}

int queue::operator-()
{
    int i;
    list* p;
    if (!head)
    {
        cout << "List empty.\n";
        return 0;
    }
    // 队列从头部取出元素
    i = head->num;
    p = head;
    head = head->next;
    delete p;
    return i;
}

list& stack::operator+(int i)
{
    list* item;
    item = new stack;
    if (!item)
    {
        cout << "Allocation error.\n";
        exit(1);
    }
    item->num = i;
    // 栈元素插入到头部
    if (head)
        item->next = head;
    head = item;
    if (!tail)
        tail = head;
    return *this;
}

int stack::operator-()
{
    int i;
    list* p;
    if (!head)
    {
        cout << "List empty.\n";
        return 0;
    }
    // 栈从头部取出元素
    i = head->num;
    p = head;
    head = head->next;
    delete p;
    return i;
}

补充说明:代码中添加了override关键字显式标记虚函数重写,可以在编译阶段检查重写合法性,避免签名不匹配导致的重写失效问题;补充了<cctype>头文件引入tolower函数声明,避免部分编译环境下的隐式声明警告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:12:17