c++primer,自定义一个复数类
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 #include<algorithm> 5 #include<cstdio> 6 #include<complex> 7 using namespace std; 8 9 class Complex{ 10 //复数为直角坐标形式,a+bj 11 private: 12 double real; 13 double image; 14 public: 15 Complex() :real(0), image(0){};// default constructor,初始化为0 16 Complex(double real, double image){ this->real = real; this->image = image; }//提供来了Complex c(0,1)的初始形式 17 Complex(const Complex& rhs){ (*this).real = rhs.real; image = rhs.image; } 18 ~Complex(){ /*cout << "deconstructor called\n";*/ } 19 double getReal()const{ return real; } 20 double getImage()const{ return image; } 21 22 //operator overload 23 Complex operator + (const Complex&rhs) //不能返回局部变量的引用,因为返回的是变量本身,变量随着函数结束会销毁掉 24 { 25 Complex result; 26 result.real= real + rhs.real; 27 result.image = image + rhs.image; 28 return result; 29 } 30 Complex operator-(const Complex&rhs) //注释掉的代码有错误,b-a得到一个表达式值,但b和a的值本身是没变的 31 { 32 /*real = real - rhs.real; 33 image = image - rhs.image; 34 return *this;*/ 35 Complex result; 36 result.real = real - rhs.real; 37 result.image = image - rhs.image; 38 return result; 39 } 40 Complex&operator=(const Complex&rhs) 41 { 42 cout << "= called\n"; 43 //简化版本 44 real = rhs.real; 45 image = rhs.image; 46 return *this; 47 } 48 /*ostream& operator<< (ostream&os)// 调用形式不符合平时输出习惯 49 { 50 if (image<0) 51 os << real << image << "j" ; 52 else os << real << "+" << image << "j"; 53 return os; 54 }*/ 55 friend ostream& operator<<(ostream&os ,const Complex &lhs); 56 }; 57 ostream& operator<<(ostream&os, const Complex &lhs) 58 { 59 if (lhs.image < 0) os << lhs.real << lhs.image << "j"; 60 else os << lhs.real << "+" << lhs.image << "j"; 61 return os; 62 } 63 int main() 64 { 65 Complex a; //申请的内存分配在栈上 66 /*a << cout<<endl;*/ 67 Complex b(2, 4); 68 /*b << cout << endl;*/ 69 Complex c(b); 70 71 Complex d = b+c;//=是初始化,调用拷贝构造函数,而不是重载运算符= 72 /*d << cout << endl;*/ 73 Complex e(3, -3); 74 /*e << cout << endl; 75 b << cout << endl;*/ 76 a = b + e; 77 a = b - e; 78 /*a << cout << endl;*/ 79 Complex f = { 1, 2 }; 80 cout << a << "\n" << b << "\n" << c << endl; 81 cout << d << "\n" << e<<"\n" << f << endl; 82 vector<Complex> cv(10); 83 cv.push_back(f); 84 for (auto x:cv) 85 { 86 cout << x << endl; 87 } 88 89 }
一些问题:
假设自定义了一个Complex类
Q:为什么需要自定义默认构造函数?
A:相比需要显示提供参数的constructor,前者不需要用户提供初始值,如Complex s,如果要用vector容纳Complex对象,要求Complex有自定义的默认构造函数,如下用法才能work:
Vector<Complex> cv(n),n个默认初始化的复数对象。
Q:定义单参构造函数有什么问题?
A:单参构造函数是一个隐式转换函数,如Complex c=7,会把右边的int转换为一个复数对象,加上explicit修饰该函数,能禁止这种隐式转换,只能使用直接初始化形式:Complex c(7)
Q:copy constructor的参数必须是引用,编译器禁止使用类型参数
A:如果是类型参数,Complex(Complex arg),参数传递时会构造实参的一个副本,循环调用拷贝构造函数,如果参数是引用,Complex(Complex&arg),使用的是实参本身,而且必须要加上const,因为non-const引用不接受const引用类型的实参。
Q:Complex的析构函数,deconstructor的函数体写法?
A:复数有两个private成员,都是double,析构时需要做什么工作?如果成员变量有指针,可以把指针置为空。
Q:重载输出运算符,只能overload为该类的友元函数?
A:如果是成员函数,ostream& operator<<(ostream& os),使用时的形式为c.operator<<cout<<endl或c<<cout<<endl;如果是非成员函数,要访问私有变量,需要在类内声明为友元:friend ostream& operator<<(ostream& os,const Complex&rhs ),调用形式为:cout<<c<<endl;
Q:重载赋值运算符与拷贝初始化的区别?
A:Complex a=c;这调用了copy ctr,而不是assingn operator,a=c+c,调用了重载的operator+和operator=,编译器如何区分调用哪一种函数?