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

C++重载operator+相加Student类指针对象报类型错误问题

错误根因

你遇到的编译错误核心是对C++运算符重载的生效规则理解有误:

  • C++ 不支持重载两个原生指针类型的运算符。你定义的成员函数Student* operator+(Student* st),要求左操作数必须是Student类型的实例本身,而非Student*指针。
  • 你在main函数中定义的s1、s2都是Student*类型的指针,直接写s1 + s2时,编译器会默认执行原生指针的算术运算:指针做加法只能接受整数/枚举类型作为偏移量,你传入另一个Student*指针作为右操作数,完全不符合原生指针加法的语法要求,因此抛出对应编译错误。

除此之外你的代码还存在几个逻辑问题:

  • 求和逻辑硬编码数组长度为5,完全没有使用类中存储的marksCount成员,一旦两个学生的分数数组长度不一致,会直接触发内存越界
  • 运算符返回堆上分配的指针不符合C++运算符的通用语义,+运算的常规预期是返回一个新的值对象,而非需要手动释放的堆指针
  • 类中持有动态分配的数组却没有定义析构函数释放内存,存在明确的内存泄漏风险
修正方法
  1. 调整operator+的签名:左操作数为当前Student实例(隐式*this),右操作数使用const Student&类型的常量引用传参,返回值为Student值类型
  2. 求和前校验两个对象的marksCount是否一致,求和循环使用marksCount作为边界,不要硬编码长度
  3. 对指针类型的对象执行加法时,先解引用拿到实例本身再参与运算,不要直接对两个指针做+操作
  4. 补全析构函数,释放动态申请的marks数组内存,避免泄漏

修正后的可运行代码如下:

#include <iostream>
#include <stdexcept>

using namespace std;

class Student
{
private:
    int* marks;
    int marksCount;

public:
    Student(int* marks, int marksCount)
    {
        this->marks = marks;
        this->marksCount = marksCount;
    }

    // 补全析构函数释放动态内存
    ~Student()
    {
        delete[] marks;
    }

    // 修正operator+签名,接收常量引用,返回值对象
    Student operator+(const Student& st)
    {
        // 校验分数长度一致
        if (this->marksCount != st.marksCount)
        {
            throw invalid_argument("两个学生的分数数组长度不一致,无法求和");
        }
        int* resMarks = new int[marksCount];
        for (int i = 0; i < marksCount; i++)
        {
            resMarks[i] = this->marks[i] + st.marks[i];
        }
        return Student(resMarks, marksCount);
    }

    int* getMarks()
    {
        return marks;
    }
    void setMarks(int* marks, int SIZE)
    {
        for (int i = 0; i < SIZE; i++)
        {
            this->marks[i] = marks[i];
        }
    }
    int getMarksCount()
    {
        return marksCount;
    }
    void setMarksCount(int count)
    {
        marksCount = count;
    }

    static void printMarks(Student& s)
    {
        for (int i = 0; i < s.getMarksCount(); i++)
        {
            cout << s.getMarks()[i] << " ";
        }
        cout << endl;
    }
};

int main()
{
    const int SIZE = 5;
    int* marks1 = new int[SIZE] { 2, 3, 5, 4, 1 };
    int* marks2 = new int[SIZE] { 4, 2, 3, 1, 2 };

    Student* s1 = new Student(marks1, SIZE);
    Student* s2 = new Student(marks2, SIZE);

    // 先解引用指针拿到实例,再执行加法
    Student s = *s1 + *s2;

    cout << "s1分数:";
    Student::printMarks(*s1);
    cout << "s2分数:";
    Student::printMarks(*s2);
    cout << "求和后分数:";
    Student::printMarks(s);

    // 手动释放堆上的s1、s2
    delete s1;
    delete s2;
    return 0;
}

运行后输出结果为:

s1分数:2 3 5 4 1 
s2分数:4 2 3 1 2 
求和后分数:6 5 8 5 3 

如果你坚持要返回Student*指针类型,只需要调整加法后的接收逻辑,但依然不能直接对两个指针做+运算,需要显式调用成员函数:

Student* s = (*s1).operator+(*s2);
// 后续使用完s需要手动delete释放

这种写法不符合运算符重载的常规使用习惯,不推荐使用。

内容的提问来源于stack exchange,提问作者Дмитро Піскарьов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:45:47