- C++根据 *** 作数的数目和类型来决定采用哪种 *** 作。
- 将*运算符用于地址,将得到存储在这个地址中的值;但将它用于两个数字时,得到的将是它们的乘积。
- C++允许将运算符重载扩展到用户定义的类型。例如,允许使用+将两个对象相加。
- 要重载运算符,需使用被称为运算符函数的特殊函数形式。
operatorop(argument-list)
- operator +( )重载+运算符,operator ( )重载运算符。[ ]是数组索引运算符。
district2 = sid + sara;
// 编译器发现,这三个 *** 作数有一个是用户自定义的类型,
// 因此使用相应的运算符函数替换上述运算符:
district2 = sid.operator+(sara);
// 隐式地使用sid(因为它调用了方法)
// 显式地使用 sara对象(因为它被作为参数传递),来计算总和,并返回这个值。
11.2 计算时间:一个运算符重载示例
- 将参数声明为引用的目的是为了提高效率。 如果按值传递Time对象,代码的功能将相同,但传递引用,速度将更快,使用的内存将更少。
- 使用返回类型 Time意味着程序将在删除sum之前构造它的拷贝,调用函数将得到该拷贝。
- 不要返回指向局部变量或临时对象的引用。函数执行完毕后,局部变量和临时对象将消失, 引用将指向不存在的数据。
- 重载后的运算符必须至少有一个 *** 作数是用户定义的类型,这将防止用户为标准类型重载运算符。
- 使用运算符时不能违反运算符原来的句法规则。例如,不能将求模运算符(%)重载成使用一个 *** 作数。
- 不能修改运算符的优先级。
- 不能创建新运算符。例如,不能定义operator **( )函数来表示求幂。
- 有些运算符只能通过成员函数进行重载。 =赋值运算符。 ( )函数调用运算符。 [ ]下标运算符。 ->通过指针访问类成员的运算符。
- 有些运算符不能重载。 sizeof运算符。 .成员运算符。 . *成员指针运算符。 ::作用域解析运算符。 ?:条件运算符。 typeid一个RTTI运算符。 const_cast强制类型转换运算符。 dynamic_cast强制类型转换运算符。 reinterpret_cast强制类型转换运算符。static_cast强制类型转换运算符。
mytime0.h
#ifndef PRIMERPLUS_MYTIME0_H
#define PRIMERPLUS_MYTIME0_H
#include
using namespace std;
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m = 0);
void AddMin(int m);
void Addhr(int h);
void Reset(int h = 0, int m = 0);
Time Sum(const Time &t) const;
Time operator+(const Time &t) const; // 重载运算符+
Time operator-(const Time &t) const; // 重载运算符-
Time operator*(double n) const; // 重载运算符*,*左边 *** 作数必须是类对象
void show() const;
// 只有类声明可以决定哪一个函数是友元,以下是非成员友元函数
// friend Time operator*(double m, const Time & t); // 重载运算符*,*左边 *** 作数左侧是double值
friend Time operator*(double m, const Time & t) { return t * m;} // 内联函数,其中使用成员函数重载运算符*
friend ostream & operator<<(ostream & os, const Time & t); // 重载运算符<<
};
#endif //PRIMERPLUS_MYTIME0_H
mytime0.cpp
#include "mytime0.h"
Time::Time()
{
hours = minutes = 0;
}
Time::Time(int h, int m)
{
hours = h;
minutes = m;
}
void Time::AddMin(int m)
{
minutes += m;
hours += minutes / 60;
minutes %= 60;
}
void Time::Addhr(int h)
{
hours += h;
}
void Time::Reset(int h, int m)
{
hours = h;
minutes = m;
}
Time Time::Sum(const Time &t) const
{
Time sum;
sum.minutes = minutes + t.minutes;
sum.hours = hours + t.hours + sum.minutes / 60;
sum.minutes %= 60;
return sum;
}
// 运算符重载+
Time Time::operator+(const Time &t) const
{
Time sum;
sum.minutes = minutes + t.minutes;
sum.hours = hours + t.hours + sum.minutes / 60;
sum.minutes %= 60;
return sum;
}
Time Time::operator-(const Time &t) const
{
Time diff;
int tot1, tot2;
tot1 = t.minutes + 60 * t.hours;
tot2 = minutes + 60 * hours;
if (tot2 > tot1)
{
diff.minutes = (tot2 - tot1) % 60;
diff.hours = (tot2 - tot1) / 60;
}
else
{
diff.minutes = (tot1 - tot2) % 60;
diff.hours = (tot1 - tot2) / 60;
}
return diff;
}
Time Time::operator*(double n) const
{
Time result;
long totalminutes = hours * n * 60 + minutes * n;
result.hours = totalminutes / 60;
result.minutes = totalminutes % 60;
return result;
}
void Time::show() const
{
cout << hours << " hours, " << minutes << " minutes." << endl;
}
// 友元函数定义,不需要限定符,不需要关键字,可以使用私有成员
//Time operator*(double m, const Time & t)
//{
// Time result;
// long totalminutes = t.hours * m * 60 + t.minutes * m;
// result.hours = totalminutes / 60;
// result.minutes = totalminutes % 60;
// return result;
//}
// operator<<( )直接访问Time对象的私有成员,所以它必须是Time类的友元。
ostream & operator<<(ostream & os, const Time & t)
{
os << t.hours << " hours, " << t.minutes << " minutes." << endl;
return os;
}
usemytime0.cpp
#include "mytime0.h"
int main(void)
{
Time t1;
Time t2(4, 20);
Time t3;
t3 = t2.Sum(t1);
t3 = t2.operator+(t1); // t3 = t1 + t2;
Time t4;
t4 = t3 + t2 + t1; // + 加号两边都是类对象,调用成员函数,重载运算符+
t4.show();
Time t5;
t5 = t4 - t3; // - 减号两边都是类对象,调用成员函数,重载运算符-
t5.show();
Time t6;
t6 = t5 * 3.0; // * 左边 *** 作数是类对象,调用成员函数,重载运算符*
t6.show();
t6 = 2.1 * t5; // * 右边 *** 作数是类对象,调用非成员友元函数,重载运算符*
t6.show();
cout << "t6:" << t6;// << 右边是类对象,调用非成员友元函数,重载运算符<<
return 0;
}
11.3 友元函数
- 通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。可以访问类的私有成员。
- 如果要为类重载运算符,并将非类的项作为其第一个 *** 作数,则可以用友元函数来反转 *** 作数的顺序。
- 非成员函数不是由对象调用的,它使用的所有值(包括对象)都是显式参数。
- 对于成员函数版本来说,一个 *** 作数通过this指针隐式地传递,另一个 *** 作数作为函数参数显式地传递;
- 对于友元版本来说,两个 *** 作数都作为参数来传递。
- 第一步,将其原型放在类声明中,并在原型声明前加上关键字friend:
friend Time operator*(double m, const Time & t);
- 第二步,编写函数定义。不需要限定符和friend。
- 友元函数不是成员函数,因此不能使用成员运算符来调用,但它与成员函数的访问权限相同。
- 只有类声明可以决定哪一个函数是友元函数。
// 在Time类中声明,只有类声明可以决定哪一个函数是友元
friend Time operator*(double m, const Time & t); // 非成员友元函数
// friend Time operator*(double m, const Time & t) { return t * m;} // 内联函数,其中使用成员函数重载运算符*
// 友元函数定义,不需要限定符,不需要关键字,可以使用私有成员
Time operator*(double m, const Time & t)
{
Time result;
long totalminutes = t.hours * m * 60 + t.minutes * m;
result.hours = totalminutes / 60;
result.minutes = totalminutes % 60;
return result;
}
// 调用
Time t5(12, 20);
Time t6;
t6 = 2.1 * t5; // * 右边 *** 作数是类对象,调用非成员友元函数,重载运算符*
11.3.2 常用的友元:重载<<运算符,以便用于输出。
想要用cout << t6;
来直接显示类对象t6,<< 右边是类对象,则使用非成员友元函数来重载运算符<<。
// 声明
friend ostream & operator<<(ostream & os, const Time & t); // 重载运算符<<
// 定义
// operator<<( )直接访问Time对象的私有成员,所以它必须是Time类的友元。
// 注意返回是一个ostream的引用
ostream & operator<<(ostream & os, const Time & t)
{
os << t.hours << " hours, " << t.minutes << " minutes." << endl;
}
// 调用
Time t6;
cout << "t6:" << t6; // << 右边是类对象,调用非成员友元函数,重载运算符<<
11.5 再谈重载:一个矢量类
- 类非常适于在一个对象中表示实体的不同方面。首先在一个对象中存储多种表示方式;然后,编写这样的类函数,以便给一种表示方式赋值时,将自动给其他表示方式赋值。
- 如果方法通过计算得到一个新的类对象,则应考虑是否可以使用类构造函数来完成这种工作。这样做不仅可以避免麻烦,而且可以确保新的对象是按照正确的方式创建的。
- 因为运算符重载是通过函数来实现的,所以只要运算符函数的特征标不同,使用的运算符数量与相应的内置C++运算符相同,就可以多次重载同一个运算符。
vector.h
#ifndef PRIMERPLUS_VERTOR_H
#define PRIMERPLUS_VERTOR_H
#include
#include
using namespace std;
namespace VECTOR
{
class Vector
{
public:
enum Mode {RECT, POL};
// 外部使用POL时要加上类名称和限定符,或者声明using VECTOR::Vector;
private:
double x; // 直角坐标x
double y; // 直角坐标y
double mag; // 极坐标长度
double ang; // 极坐标角度
Mode mode; // 枚举变量
void set_mag();
void set_ang();
void set_x() {x = mag * cos(ang);}
void set_y() {y = mag * sin(ang);}
public:
Vector();
Vector(double n1, double n2, Mode form = RECT);
void reset(double n1, double n2, Mode form = RECT);
~Vector();
double xval() const {return x;} // 在类声明中定义,自动成为内联函数
double yval() const {return y;}
double magval() const {return mag;}
double angval() const {return ang;}
void polar_mode() {mode = POL;}
void rect_mode() {mode = RECT;}
Vector operator+(const Vector & b) const;
Vector operator-(const Vector & b) const;
Vector operator-() const; // 重载运算符-,进行取反 *** 作
Vector operator*(double n) const; // 使用格式:类的对象 * 放大倍数
friend Vector operator*(double n, const Vector & a) {return a * n;}
friend ostream & operator<<(ostream & os, const Vector & v);
};
}
#endif
vector.cpp
#include "vector.h"
namespace VECTOR
{
const double Rad_to_deg = 45.0 / atan(1.0);
void Vector::set_mag()
{
mag = sqrt(x*x + y*y);
}
void Vector::set_ang()
{
if (x == 0.0 && y == 0.0)
ang = 0;
else
ang = atan2(y, x); // 弧度制
}
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = RECT;
}
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL)
{
mag = n1;
ang = n2 / Rad_to_deg; // 角度转换到弧度
set_x();
set_y();
}
else
{
cout << "ERROR." << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
void Vector::reset(double n1, double n2, Mode form)
{
mode = form;
if (form == RECT)
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if (form == POL)
{
mag = n1;
ang = n2 / Rad_to_deg; // 角度转换到弧度
set_x();
set_y();
}
else
{
cout << "ERROR." << endl;
x = y = mag = ang = 0.0;
mode = RECT;
}
}
Vector::~Vector()
{
}
Vector Vector::operator+(const Vector & b) const
{
return Vector(x + b.x, y + b.y);
}
Vector Vector::operator-(const Vector & b) const
{
return Vector(x - b.x, y- b.y); // 注意!!!这里使用 x 和 y 为前项
// 从隐式矢量参数减去以显式参数传递的矢量
}
Vector Vector::operator-() const
{
return Vector(-x, -y);
}
Vector Vector::operator*(double n) const
{
return Vector(x*n, y*n);
}
ostream & operator<<(ostream & os, const Vector & v)
{
if (v.mode == Vector::POL) //注意这里的POL要加上类限定符,友元函数不在类作用域
os << "mag, nag : " << v.mag << ", " << v.ang << endl;
else if (v.mode == Vector::RECT)
os << "x, y : " << v.x << ", " << v.y << endl;
else
os << "ERROR." << endl;
return os;
}
}
usevector.cpp
// randwalk.cpp -- using the Vector class
#include
#include // rand(), srand() prototypes
#include // time() prototype
#include "vector.h"
int main()
{
using namespace std;
using VECTOR::Vector;
srand(time(0)); // seed random-number generator
double direction;
Vector step;
Vector result(0.0, 0.0);
unsigned long steps = 0;
double target;
double dstep;
cout << "Enter target distance (q to quit):";
while (cin >> target)
{
cout << "Enter step length:";
if (!(cin >> dstep))
break;
while (result.magval() < target)
{
direction = rand() % 360;
step.reset(dstep, direction, Vector::POL);
result = result + step;
steps++;
}
cout << "After " << steps << " steps, the subject has the following location:\n";
cout << result << endl;
result.polar_mode();
cout << " or\n" << result << endl;
cout << "Average outward distance per step = " << result.magval()/steps << endl;
steps = 0;
result.reset(0.0, 0.0);
cout << "Enter target distance (q to quit):";
}
cout << "Bye!\n";
cin.clear();
while (cin.get() != '\n')
continue;
return 0;
}
11.6 类的自动转换和强制类型转换
C++语言不自动转换不兼容的类型。
从参数类型到类类型的转换:
- 只接受一个参数的构造函数:定义了从参数类型到类类型的转换。可以用于隐式和显示转换。
- 如果使用关键字
explicit
限定了这种构造函数,则它只能用于显示转换。
Stonewt(double lbs); // Stonewt类声明中的构造函数
Stonewt incognito = 275; // 类的自动隐式转换,将int数字转换成类的对象,创建临时对象,传递给incognito
Stonewt incognito_ = Stonewt(275); // 创建一个临时的无名的类对象,传递给incognito_
// 加关键字就不会自动类型转换,需要显示转换
explicit Stonewt(double lbs);
Stonewt incognito_ = Stonewt(275); // 显示转换,创建一个临时的无名的类对象,传递给incognito_
从类类型到其他类型的转换:
- C++运算符函数——转换函数:可以实现从类类型到其他类型的转换。
- 转换函数是用户定义的强制类型转换,可以像使用强制类型转换那样使用它们。
- 如果使用关键字
explicit
限定了转换函数,则它只能用于显示转换。
如何创建转换函数呢?
- 要转换为typeName类型,需要使用这种形式的转换函数:
operator typeName();
- 转换函数必须是类方法; 需要通过类对象来调用。
- 转换函数不能指定返回类型; typeName指出了要转换成的类型。
- 转换函数不能有参数。
// 如果定义了从Stonewt类到double的转换函数
operator double() const;
explicit operator double() const; // 如果加了关键字后,只能显示转换
// 编译器发现,右侧是Stonewt类型,而左侧是double类型,因此它将查看程序员是否定义了与此匹配的转换函数。
Stonewt wolfe(285.7);
double hello = wolfe; // 隐式
double host = double (wolfe); // 显示,syntax #1
double thinker = (double) wolfe; // 显示,syntax #2
stonewt.h
#ifndef PRIMERPLUS_STONEWT_H
#define PRIMERPLUS_STONEWT_H
class Stonewt
{
private:
// 在类里定义const常量不会在内存中保留
enum {Lbs_per_stn = 14}; // pounds per stone
int stone; // 英石
double pds_left; // 磅
double pounds; // 总磅
public:
// explicit Stonewt(double lbs); // 加关键字explicit就不会自动隐式类型转换
Stonewt(double lbs); // 只有接受一个参数的构造函数才能作为转换函数。
Stonewt(int stn, double lbs);
Stonewt();
~Stonewt();
void show_lbs() const; // show weight in pounds format
void show_stn() const; // show weight in stone format
operator int() const; // 转换函数
operator double() const;
};
#endif //PRIMERPLUS_STONEWT_H
stonewt.cpp
// stonewt.cpp -- Stonewt methods
#include
using std::cout;
#include "stonewt.h"
Stonewt::Stonewt(double lbs)
{
stone = int (lbs) / Lbs_per_stn; // integer division
pds_left = int (lbs) % Lbs_per_stn + lbs - int(lbs);
pounds = lbs;
}
// construct Stonewt object from stone, double values
Stonewt::Stonewt(int stn, double lbs)
{
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn +lbs;
}
Stonewt::Stonewt() // default constructor, wt = 0
{
stone = pounds = pds_left = 0;
}
Stonewt::~Stonewt() // destructor
{}
// show weight in stones
void Stonewt::show_stn() const
{
cout << stone << " stone, " << pds_left << " pounds\n";
}
// show weight in pounds
void Stonewt::show_lbs() const
{
cout << pounds << " pounds\n";
}
// conversion functions
Stonewt::operator int() const
{
return int (pounds + 0.5);
}
Stonewt::operator double() const
{
return pounds;
}
usestonewt.cpp
// stone.cpp -- user-defined conversions
// compile with stonewt.cpp
#include
using std::cout;
using std::endl;
#include "stonewt.h"
void display(const Stonewt & st, int n);
int main()
{
// 只有接受一个参数的构造函数才能作为转换函数。
cout << "-------------------construct function--------------------" << endl;
Stonewt incognito = 275; // 类的自动转换,将数字转换成类的对象,创建临时对象,传递给incognito
Stonewt incognito_ = Stonewt(275); // 创建一个临时的无名的类对象,传递给incognito_
Stonewt wolfe(285.7); // 构造函数用于将double类型的值转换为Stonewt类型
Stonewt taft(21, 8);
cout << "The celebrity weighed ";
incognito.show_stn();
cout << "The detective weighed ";
wolfe.show_stn();
cout << "The President weighed ";
taft.show_lbs();
cout << "---------------------------------------" << endl;
incognito = 276.8; // uses constructor for conversion
taft = 325; // same as taft = Stonewt(325);
cout << "After dinner, the celebrity weighed ";
incognito.show_stn();
cout << "After dinner, the President weighed ";
taft.show_lbs();
cout << "---------------------------------------" << endl;
display(taft, 2);
cout << "The wrestler weighed even more.\n";
display(422, 2);
cout << "No stone left unearned\n";
cout << "-------------------conversion functions--------------------" << endl;
Stonewt poppins(9,2.8); // 9 stone, 2.8 pounds
double p_wt = poppins; // implicit conversion
cout << "Convert to double => ";
cout << "Poppins: " << p_wt << " pounds.\n";
cout << "Convert to int => ";
cout << "Poppins: " << int (poppins) << " pounds.\n";
return 0;
}
void display(const Stonewt & st, int n)
{
for (int i = 0; i < n; i++)
{
cout << "Wow! ";
st.show_stn();
}
}
11.7 总结
- 一般来说,访问私有类成员的唯一方法是使用类方法。C++使用友元函数来避开这种限制。要让函数成为友元,需要在类声明中声明该函数,并在声明前加上关键字
friend
。 - C++扩展了对运算符的重载,允许自定义特殊的运算符函数,这种函数描述了特定的运算符与类之间的关系。运算符函数可以是类成员函数,也可以是友元函数(有一些运算符函数只能是类成员函数)。要调用运算符函数,可以直接调用该函数,也可以以通常的句法使用被重载的运算符。
- 对于运算符op,其运算符函数的格式如下:
operatorop(argument-list)
,argument-list表示该运算符的 *** 作数。如果运算符函数是类成员函数,则第一个 *** 作数是调用对象,它不在argument-list中。例如,本章通过为Vector类定义operator +( )成员函数重载了加法。如果up、right和result都是Vector对象,则可以使用下面的任何一条语句来调用矢量加法:result = up.operator+(right);``result = up + right;
在第二条语句中,由于 *** 作数up和right的类型都是Vector,因此 C++将使用Vector的加法定义。 - 当运算符函数是成员函数时,则第一个 *** 作数将是调用该函数的对象。例如,在前面的语句中,up对象是调用函数的对象。定义运算符函数时,如果要使其第一个 *** 作数不是类对象,则必须使用友元函数。这样就可以将 *** 作数按所需的顺序传递给函数了。
- 最常见的运算符重载任务之一是定义<<运算符,使之可与cout一起使用,来显示对象的内容。要让ostream对象成为第一个操作数,需要将运算符函数定义为友元;要使重新定义的运算符能与其自身拼接,需要将返回类型声明为ostream &。下面的通用格式能够满足这种要求:然而,如果类包含这样的方法,它返回需要显示的数据成员的值,则可以使用这些方法,无需在operator<<( )中直接访问这些成员。在这种情况下,函数不必(也不应当)是友元。
ostream & operator<<(ostream & os, const c_name & obj)
{
os << ... ; // display object contents
return os;
}
- C++允许指定在类和基本类型之间进行转换的方式。首先,任何接受唯一一个参数的构造函数都可被用作转换函数,将类型与该参数相同的值转换为类。如果将类型与该参数相同的值赋给对象,则C++将自动调用该构造函数。
例如,假设有一个String类,它包含一个将char *值作为其唯一参数的构造函数,那么如果bean是String对象,则可以使用下面的语句:
bean = "pinto";
// converts type char * to type String.
然而,如果在该构造函数的声明前加上了关键字explicit
,则该构造函数将只能用于显式转换:
bean = String("pinto");
// converts type char * to type String explicitly - 要将类对象转换为其他类型,必须定义转换函数,指出如何进行这种转换。转换函数必须是成员函数。将类对象转换为typeName类型的转换函数的原型如下:
operator typeName();
注意,转换函数没有返回类型、没有参数,但必须返回转换后的值(虽然没有声明返回类型)。例如,下面是将Vector转换为double类型的函数:
Vector::operator double()
{
...
return a_double_value;
}
11.8 复习题
1.使用成员函数为Stonewt类重载乘法运算符,该运算符将数据成员与double类型的值相乘。注意,用英石和磅表示时,需要进位。也就是说,将10英石8磅乘以2等于21英石2磅。 (一英石等于14磅)
// prototype
Stonewt operator*(double mult);
// definition - let constructor do the work
Stonewt Stonewt::operator*(double mult)
{
return Stonewt(mult * pounds);
}
4.使用友元函数为Stonewt类重载乘法运算符,该运算符将double值与Stone值相乘。
// prototype
friend Stonewt operator*(double mult, const Stonewt & s);
// definetion - let constructor do the work
Stonewt operator*(double mult, const Stonewt & s)
{
return Stonewt(mult * s.pounds);
}
2.友元函数与成员函数之间的区别是什么?
成员函数是类定义的一部分,通过特定的对象来调用。成员函数可以隐式访问调用对象的成员,而无需使用成员运算符。
友元函数不是类的组成部分,因此被称为直接函数调用。友元函数不能隐式访问类成员,而必须将成员运算符用于作为参数传递的对象。
3.非成员函数必须是友元才能访问类成员吗?
要访问私有成员,它必须是友元,但要访问公有成员,可以不是友元。
5.哪些运算符不能重载?
【sizeof】【.】【.*】【::】【?:】
6.在重载运算符=、( )、[ ]和->时,有什么限制?
这些运算符必须使用成员函数来定义。
7.为Vector类定义一个转换函数,将Vector类转换为一个double类型的值,后者表示矢量的长度。
operator double() {return mag;}
11.9 编程练习
p7.h
#ifndef __COMPLEX_0_H__
#define __COMPLEX_0_H__
#include
using namespace std;
class complex
{
private:
double real;
double imaginary;
public:
complex();
complex(double r, double i);
complex operator+(const complex &c) const;
complex operator-(const complex &c) const;
complex operator*(const complex &c) const;
complex operator~() const;
friend complex operator*(double x, const complex &c);
friend istream &operator>>(istream &is, complex &c);
friend ostream &operator<<(ostream &os, const complex &c);
};
#endif
p7.cpp
#include "complex0.h"
complex::complex()
{
real = imaginary = 0.0;
}
complex::complex(double r, double i)
{
real = r;
imaginary = i;
}
complex complex::operator+(const complex &c) const
{
return complex(real+c.real, imaginary+c.imaginary);
}
complex complex::operator-(const complex &c) const
{
return complex(real-c.real, imaginary-c.imaginary);
}
complex complex::operator*(const complex &c) const
{
return complex(real*c.real - imaginary*c.imaginary, real*c.imaginary + imaginary*c.real);
}
complex complex::operator~() const
{
return complex(real, -imaginary);
}
complex operator*(double x, const complex &c)
{
return complex(x*c.real, x*c.imaginary);
}
istream &operator>>(istream &is, complex &c)
{
is >> c.real >> c.imaginary;
return is;
}
ostream &operator<<(ostream &os, const complex &c)
{
os << "real = " << c.real << ", imaginary = " << c.imaginary << endl;
return os;
}
mainp7.cpp
#include
#include "complex0.h"
using namespace std;
int main(void)
{
complex a(3.0, 4.0);
complex c;
cout << "Enter a complex number (q to quit): \n";
while(cin >> c)
{
cout << "c is " << c << endl;
cout << "complex conjugate is " << ~c << endl;
cout << "a is " << a << endl;
cout << "a + c is " << a + c << endl;
cout << "a - c is " << a - c << endl;
cout << "a * c is " << a * c << endl;
cout << "2 * c is " << 2 * c << endl;
cout << "Enter a complex number (q to quit): \n";
}
cout << "Done\n";
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)