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=,编译器如何区分调用哪一种函数?

posted @ 2017-07-21 14:16  hchacha  阅读(1386)  评论(0编辑  收藏  举报