C++重载operator+相加Student类指针对象报类型错误问题
错误根因
你遇到的编译错误核心是对C++运算符重载的生效规则理解有误:
- C++ 不支持重载两个原生指针类型的运算符。你定义的成员函数
Student* operator+(Student* st),要求左操作数必须是Student类型的实例本身,而非Student*指针。 - 你在main函数中定义的
s1、s2都是Student*类型的指针,直接写s1 + s2时,编译器会默认执行原生指针的算术运算:指针做加法只能接受整数/枚举类型作为偏移量,你传入另一个Student*指针作为右操作数,完全不符合原生指针加法的语法要求,因此抛出对应编译错误。
除此之外你的代码还存在几个逻辑问题:
- 求和逻辑硬编码数组长度为5,完全没有使用类中存储的
marksCount成员,一旦两个学生的分数数组长度不一致,会直接触发内存越界 - 运算符返回堆上分配的指针不符合C++运算符的通用语义,
+运算的常规预期是返回一个新的值对象,而非需要手动释放的堆指针 - 类中持有动态分配的数组却没有定义析构函数释放内存,存在明确的内存泄漏风险
修正方法
- 调整
operator+的签名:左操作数为当前Student实例(隐式*this),右操作数使用const Student&类型的常量引用传参,返回值为Student值类型 - 求和前校验两个对象的
marksCount是否一致,求和循环使用marksCount作为边界,不要硬编码长度 - 对指针类型的对象执行加法时,先解引用拿到实例本身再参与运算,不要直接对两个指针做
+操作 - 补全析构函数,释放动态申请的
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,提问作者Дмитро Піскарьов
相关产品推荐
相关产品推荐

