#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. [Linux] 002 预备知识

    1. 开源软件 (1) 常见开源软件 Apache NGINXTM MySQL PHP Saamba mongoDB Python Ruby Sphinx -- (2) 开源软件的特点 绝大多数开源软 ...

  2. Netty之大动脉Pipeline

    Pipeline 设计原理 Channel 与ChannelPipeline: 相信大家都已经知道,在Netty 中每个Channel 都有且仅有一个ChannelPipeline 与之对应,它们的组 ...

  3. java Semaphore信号灯

    Semaphore实现的功能就类似2个公用电话,假如有10个人要打电话:那么只能2个人占有电话,8个需要等待.当2个人中 的任何一个人让开后,其中等待的另外8个人中又有一个人可以使用了等待的8个人中可 ...

  4. JVM(Java虚拟机)详解(JDK7)

    1.Java内存区域 运行时数据区域: Java 虚拟机在执行Java程序时,定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁.另外一些则是与线程 ...

  5. MIT 6.824学习笔记2 RPC/Thread

    本节内容:Lect 2   RPC and Threads 线程:Threads allow one program to (logically) execute many things at onc ...

  6. C# form 传参数的几个方法

    方法一:传值最先想到的,Form2构造函数中接收一个string类型参数,即Form1中选中行的文本,将Form2的TextBox控件的Text设置为该string,即完成了Form1向Form2的传 ...

  7. Metasploit自动攻击模块

    Metasploit自动攻击模块 Usage: db_autopwn [options] -h Display this help text -t Show all matching exploit ...

  8. UIWindow与UIView

    UIView与UIWindow * 一般应用程序只有一个UIWindow对象.所有的控件都是在UIWindow上展现的.每个UIView对象都有一个window属性,表示当前view显示在哪个窗体上. ...

  9. simple_pt时遇到的问题

    elf.c:30:18: fatal error: gelf.h: No such file or directory 安装libelf-dev 遇到找不到ldwarf apt-cache  sear ...

  10. navigate连接不上Centos7+mariadb的问题

    链接数据库时忽然遇到一个问题.Mac Navicat链接时报错Can’t connect to MySQL server on ‘xx.xx.xx.xx’ (61). PS. win版Navicat ...