#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<complex>
using namespace std; class Complex{
//复数为直角坐标形式,a+bj
private:
double real;
double image;
public:
Complex() :real(), image(){};// default constructor,初始化为0
Complex(double real, double image){ this->real = real; this->image = image; }//提供来了Complex c(0,1)的初始形式
Complex(const Complex& rhs){ (*this).real = rhs.real; image = rhs.image; }
~Complex(){ /*cout << "deconstructor called\n";*/ }
double getReal()const{ return real; }
double getImage()const{ return image; } //operator overload
Complex operator + (const Complex&rhs) //不能返回局部变量的引用,因为返回的是变量本身,变量随着函数结束会销毁掉
{
Complex result;
result.real= real + rhs.real;
result.image = image + rhs.image;
return result;
}
Complex operator-(const Complex&rhs) //注释掉的代码有错误,b-a得到一个表达式值,但b和a的值本身是没变的
{
/*real = real - rhs.real;
image = image - rhs.image;
return *this;*/
Complex result;
result.real = real - rhs.real;
result.image = image - rhs.image;
return result;
}
Complex&operator=(const Complex&rhs)
{
cout << "= called\n";
//简化版本
real = rhs.real;
image = rhs.image;
return *this;
}
/*ostream& operator<< (ostream&os)// 调用形式不符合平时输出习惯
{
if (image<0)
os << real << image << "j" ;
else os << real << "+" << image << "j";
return os;
}*/
friend ostream& operator<<(ostream&os ,const Complex &lhs);
};
ostream& operator<<(ostream&os, const Complex &lhs)
{
if (lhs.image < ) os << lhs.real << lhs.image << "j";
else os << lhs.real << "+" << lhs.image << "j";
return os;
}
int main()
{
Complex a; //申请的内存分配在栈上
/*a << cout<<endl;*/
Complex b(, );
/*b << cout << endl;*/
Complex c(b); Complex d = b+c;//=是初始化,调用拷贝构造函数,而不是重载运算符=
/*d << cout << endl;*/
Complex e(, -);
/*e << cout << endl;
b << cout << endl;*/
a = b + e;
a = b - e;
/*a << cout << endl;*/
Complex f = { , };
cout << a << "\n" << b << "\n" << c << endl;
cout << d << "\n" << e<<"\n" << f << endl;
vector<Complex> cv();
cv.push_back(f);
for (auto x:cv)
{
cout << x << endl;
} }

一些问题:

假设自定义了一个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=,编译器如何区分调用哪一种函数?

c++primer,自定义一个复数类的更多相关文章

  1. C++ 实验 使用重载运算符实现一个复数类

    实验目的: 1.掌握用成员函数重载运算符的方法 2.掌握用友元函数重载运算符的方法 实验要求: 1.定义一个复数类,描述一些必须的成员函数,如:构造函数,析构函数,赋值函数,返回数据成员值的函数等. ...

  2. JavaScript实现一个复数类

    <script type="text/javascript"> /** * 这里定义Complex类,用来描述复数 */ /** * 这个构造函数为它所创建的每个实例定 ...

  3. Java自定义一个字典类(Dictionary)

    标准Java库只包含Dictionary的一个变种,名为:Hashtable.(散列表) Java的散列表具有与AssocArray相同的接口(因为两者都是从Dictionary继承来的).但有一个方 ...

  4. java中自定义一个异常类 在某些情况抛出自定的异常 ----------阻断程序

    //=============定义异常类 package org.springblade.flow.engine.errorException; /** * 自定义异常处理写入sap失败 */ pub ...

  5. Python自定义一个数组类,支持数组之间的四则运算和其他常见方法

    class MyArray: '''保证输入的内容是整型.浮点型''' def ___isNumber(self, num): if not isinstance(num, (int,float)): ...

  6. 定义一个复数类Complex

    #include<iostream> #include<math.h> using namespace std; class Complex{ public: Complex( ...

  7. 复数类(C++练习一)

    写一个复数类,实现基本的运算,目的熟悉封装与数据抽象. 类的定义 #include <iostream> #include <vector> using namespace s ...

  8. 安卓开发37:自定义的HorizontalScrollView类,使其pageScroll的时候焦点不选中

    自定义一个HorizontalScrollView类,主要为了让这个HorizontalScrollView不能鼠标点击,不能左右按键,并且没有焦点. public class ImageMoveHo ...

  9. C++习题 复数类--重载运算符2+

    Description 定义一个复数类Complex,重载运算符"+",使之能用于复数的加法运算.参加运算的两个运算量可以都是类对象,也可以其中有一个是整数,顺序任意.例如,c1+ ...

随机推荐

  1. Codeforces 1148C(思维)

    题面 给出一个长度为n的排列a,每次可以交换序列的第i个和第j个元素,当且仅当\(2 \times |i-j| \geq n\),求一种交换方案,让序列从小到大排好序 分析 重点是考虑我们怎么把第x个 ...

  2. [BZOJ 3991][SDOI2015]寻宝游戏(dfs序)

    题面 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...

  3. Page.IsPostBack

    ASP.NET页面的执行顺序说明:Page_Init(页面初始化引发的事件)——Page_Load(加载页面时引发的事件)——ControlEvent(服务器控件引发的事件)——Page_UnLoad ...

  4. html的q标签、blockquote标签

    九层之台,起于垒土 一.<q> 定义和用法 <q> 标签定义短的引用.浏览器经常在引用的内容周围添加引号. <html> <body> <p> ...

  5. smbstatus - 报告当前 samba 的联接状态

    总览 smbstatus [-b] [-d] [-L] [-p] [-S] [-s configuration file] [-u username] 描述 此程序是 samba 套件的一部分. sm ...

  6. Class.forName的作用

    在java语言中,任何类只有被装载到JVM上才能运行.Class.forName()方法的作用就是把类加载到JVM中,它会返回一个与带有给定字符串明的类或者接口相关联的Class对象,并且JVM会加载 ...

  7. git提交代码冲突解决

    1.git stash save "说明信息" 2.git stash lish 3.git pull 4.git stash pop stash@{编号}

  8. Sass函数-值列表index

    ndex() 函数类似于索引一样,主要让你找到某个值在列表中所处的位置.在 Sass 中,第一个值就是1,第二个值就是 2,依此类推: >> index(1px solid red, 1p ...

  9. winform 自定义控件属性在属性面板中显示

    Jan.David Nothing is impossible, the word itself says 'I'm possible'!" — Audrey Hepburn winform ...

  10. js-ifelse-奇技淫巧

    我们有A,B,C,D四个不同的类别,在最开始的时候只有三个类别,并且两个类别是做同样的事: function categoryHandle(category) { if(category !== 'A ...