C++复数类实现报错:私有成员访问问题及引用函数定义疑问
嘿,我来帮你搞定代码里的bug,顺便把你关于引用的疑问讲明白~
你的代码现在有几个关键问题,咱们一个个来修:
1. 成员函数定义没加类作用域
你写的compare和add函数,现在是全局函数,不是Complex类的成员!所以它们根本访问不了类里的私有成员real和img,这就是你看到“is private within this context”错误的原因。
正确的写法是在函数名前加上Complex::,告诉编译器这是类的成员函数:
Complex& Complex::compare(Complex & c2) { // 函数内容... } Complex& Complex::add(Complex & a) { // 函数内容... }
2. 返回局部对象的引用是大坑!
你在compare和add里都创建了局部对象t和temp,这些对象在函数执行完之后就会被销毁。你返回它们的引用,就相当于返回了一个指向已经被释放内存的指针,这叫悬空引用,会导致程序崩溃或者出现莫名其妙的行为。
解决办法:要么返回对象值(把返回类型改成Complex,去掉&),要么如果要返回引用,就得确保返回的对象在函数结束后还存在(比如返回当前对象*this或者传入的参数引用)。
3. compare函数的逻辑不完整
你现在的compare只给t的real或者img赋值,另一个成员会是未初始化的垃圾值。比如如果实部相等,你只赋值了img,real就没值,输出的时候会乱码。正确的逻辑应该是完整复制较大的那个复数的所有成员。
我把所有问题都改好了,你可以直接运行试试:
#include <iostream> #include <set> #include <list> #include <cmath> using namespace std; class Complex { int real, img; public: void getdata() { cin >> real >> img; } void display() { cout << real << "+" << img << "i" << endl; } // 这里把返回类型改成Complex,不返回引用 Complex compare(const Complex & c2); Complex add(const Complex & a); }; Complex Complex::compare(const Complex & c2) { // 完整复制较大的复数 if (real > c2.real) { return *this; // 返回当前对象的值 } else if (c2.real > real) { return c2; // 返回参数对象的值 } else { // 实部相等,比较虚部 if (img >= c2.img) { return *this; } else { return c2; } } } Complex Complex::add(const Complex & a) { Complex temp; temp.real = real + a.real; temp.img = img + a.img; return temp; // 返回临时对象的值,没问题 } int main() { Complex c1, c2, c3; c1.getdata(); c2.getdata(); c3 = c1.compare(c2); c3.display(); c3 = c1.add(c2); c3.display(); return 0; }
我给你拆解一下引用在函数里的两种用法:
1. 参数里的&:引用传递
比如compare(const Complex & c2)里的&,表示把参数以引用的方式传递,而不是复制一个新的对象。这样做的好处:
- 节省内存,不用拷贝整个对象
- 可以直接访问原对象(如果不加
const还能修改它) - 这里加
const是因为我们不会修改c2,这样更安全,也能接收常量对象。
2. 返回值里的&:返回对象引用
返回引用的前提是:你返回的对象在函数结束后必须仍然存在。比如:
- 如果你的函数是要修改当前对象(比如
operator+=),可以返回*this的引用,因为当前对象在函数结束后还活着 - 但你的
add和compare是生成新对象或者返回两个中的一个,add生成的是局部临时对象,不能返回引用;compare如果返回其中一个参数的引用是可以的,比如把返回类型改成const Complex&,然后直接返回*this或者c2,这样更高效。
比如优化后的compare可以这么写(返回引用,避免拷贝):
const Complex& Complex::compare(const Complex & c2) { if (real > c2.real || (real == c2.real && img >= c2.img)) { return *this; } else { return c2; } }
这样就不需要创建临时对象,直接返回已经存在的对象的引用,安全又高效。
内容的提问来源于stack exchange,提问作者shashank chaudhary

