《C++编程思想》 第十一章 运算符重载 (习题+解答)

一.相关代码

1.

/*运算符重载语法*/
/*OPOVER.cpp*/
/*这两个重载的运算符被定义为内联成员函数。对于二元运算符,单个参数是出现在运算符
右侧的那个。当一元运算符被定义为成员函数时,没有参数。成员函数被运算符左侧的对象调
用。
对于非条件运算符(条件运算符通常返回一个布尔值),如果两个参数是相同的类型,希
望返回和运算相同类型的对象或引用。如果它们不是相同类型,它作什么样的解释就取决于程
序设计者。用这种方法可以组合复杂的表达式:
K += I + J ;
运算符+号产生一个新的整数(临时的),这个整数被用作运算符‘ +=’的r v参数。一旦这
个临时整数不再需要时就被消除。*/
#include <iostream>
using namespace std;

class integer
{
	int i;
public:
	integer(int I)
	{
		i = I;
	}
	const integer
		operator+(const integer& rv) const
	{
		cout << "operator+" << endl;
		return integer(i + rv.i);
	}
	integer&
		operator+=(const integer& rv)
	{
		cout << "operator+=" << endl;
		i += rv.i;
		return *this;
	}
};

int main()
{
	cout << "built_in types:" << endl;
	int i = 1, j = 2, k = 3;
	k += i + j;
	cout << "user-defined types:" << endl;
	integer I(1), J(2), K(3);
	K += I + J;

	return 0;
}

2.

/*UNARY.cpp*/
//一元运算符重载
#include <iostream.h>

class integer
{
	long i;
	integer* This()
	{
		return this;
	}
public:
	integer(long I = 0):i(I)
	{}
	friend const integer&
		operator+(const integer& a);
	friend const integer
		operator-(const integer& a);
	friend const integer
		operator~(const integer& a);
	friend integer*
		operator&(integer& a);
	friend int
		operator!(const integer& a);
	friend const integer&
		operator++(integer& a);//++a
	friend const integer
		operator++(integer& a, int);//a++
	friend const integer&
		operator--(integer& a);//--a
	friend const integer
		operator--(integer& a, int);//a--
};

const integer& operator+(const integer& a)
{
	cout << "+integer\n";
	return a;
}

const integer operator-(const integer& a)
{
	cout << "-integer\n";
	return integer(-a.i);
}

const integer operator~(const integer& a)
{
	cout << "~integer\n";
	return integer(~a.i);
}

integer* operator&(integer& a)
{
	cout << "&integer\n";
	return a.This();
}

int operator!(const integer& a)
{
	cout << "!integer\n";
	return !a.i;
}

const integer& operator++(integer& a)
{
	cout << "++integer\n";
	a.i++;
	return a;
}

const integer operator++(integer& a, int)
{
	cout << "integer++\n";
	integer r(a.i);
	a.i++;
	return r;
}

const integer& operator--(integer& a)
{
	cout << "--integer\n";
	a.i--;
	return a;
}

const integer operator--(integer& a, int)
{
	cout << "integer--\n";
	integer r(a.i);
	a.i--;
	return r;
}

void f(integer a)
{
	+a;
	-a;
	~a;integer* ip = &a;
	!a;
	++a;
	a++;
	--a;
	a--;
}

class byte
{
	unsigned char b;
public:
	byte(unsigned char B = 0):b(B){}
	const byte& operator+() const
	{
		cout << "+byte\n";
		return *this;
	}
	const byte operator-() const
	{
		cout << "-byte\n";
		return byte(-b);
	}
	const byte operator~() const
	{
		cout << "~byte\n";
		return byte(~b);
	}
	byte operator!() const
	{
		cout << "!byte\n";
		return byte(!b);
	}
	byte* operator&()
	{
		cout << "&byte\n";
		return this;
	}
	const byte& operator++()//++b
	{
		cout << "++byte\n";
		b++;
		return *this;
	}
	const byte operator++(int)//b++
	{
		cout << "byte++\n";
		byte before(b);
		b++;
		return before;
	}
	const byte& operator--()//--b
	{
		cout << "--byte\n";
		--b;
		return *this;
	}
	const byte operator--(int)//b--
	{
		cout << "byte--\n";
		byte before(b);
		--b;
		return before;
	}
};

void g(byte b)
{
	+b;
	-b;
	~b;
	byte* bp = &b;
	!b;
	++b;
	b++;
	--b;
	b--;
}

int main()
{
	integer a;
	f(a);
	byte b;
	g(b);

	return 0;
}

3.

/*BINARY.cpp*/
//二元运算符重载
#include <fstream.h>
#include "E:\VC++\7_31_2\allege.h"

ofstream out("binary.out");

class integer
{
	long i;
public:
	integer(long I = 0):i(I){}
	friend const integer
		operator+(const integer& left,
		          const integer& right);
	friend const integer
		operator-(const integer& left,
		          const integer& right);
	friend const integer
		operator*(const integer& left,
		          const integer& right);
	friend const integer
		operator/(const integer& left,
		          const integer& right);
	friend const integer
		operator%(const integer& left,
		          const integer& right);
	friend const integer
		operator^(const integer& left,
		          const integer& right);
	friend const integer
		operator&(const integer& left,
		          const integer& right);
	friend const integer
		operator|(const integer& left,
		          const integer& right);
	friend const integer
		operator<<(const integer& left,
		          const integer& right);
	friend const integer
		operator>>(const integer& left,
		          const integer& right);
	friend integer&
		operator+=(integer& left,
		           const integer& right);
	friend integer&
		operator-=(integer& left,
		           const integer& right);
	friend integer&
		operator*=(integer& left,
		           const integer& right);
	friend integer&
		operator/=(integer& left,
		           const integer& right);
	friend integer&
		operator%=(integer& left,
		           const integer& right);
	friend integer&
		operator^=(integer& left,
		           const integer& right);
	friend integer&
		operator&=(integer& left,
		           const integer& right);
	friend integer&
		operator|=(integer& left,
		           const integer& right);
	friend integer&
		operator>>=(integer& left,
		           const integer& right);
	friend integer&
		operator<<=(integer& left,
		           const integer& right);
	friend int
		operator==(const integer& left,
		           const integer& right);
	friend int
		operator!=(const integer& left,
		           const integer& right);
	friend int
		operator<(const integer& left,
		           const integer& right);
	friend int
		operator>(const integer& left,
		           const integer& right);
		friend int
		operator<=(const integer& left,
		           const integer& right);
	friend int
		operator>=(const integer& left,
		           const integer& right);
		friend int
		operator&&(const integer& left,
		           const integer& right);
	friend int
		operator||(const integer& left,
		           const integer& right);
	void print(ostream& os) const
	{
		os << i;
	}
};

const integer
operator+(const integer& left,
		  const integer& right)
{
	return integer(left.i + right.i);
}
const integer
operator-(const integer& left,
		  const integer& right)
{
	return integer(left.i - right.i);
}
const integer
operator*(const integer& left,
		  const integer& right)
{
	return integer(left.i * right.i);
}
const integer
operator/(const integer& left,
		  const integer& right)
{
	allege(right.i != 0,"divide by zero");
		return integer(left.i / right.i);
}
const integer
operator%(const integer& left,
		  const integer& right)
{
	allege(right.i != 0, "modulo by zero");
	return integer(left.i % right.i);
}
const integer
operator^(const integer& left,
		  const integer& right)
{
	return integer(left.i ^ right.i);
}
const integer
operator&(const integer& left,
		  const integer& right)
{
	return integer(left.i & right.i);
}
const integer
operator|(const integer& left,
		  const integer& right)
{
	return integer(left.i | right.i);
}
const integer
operator<<(const integer& left,
		   const integer& right)
{
	return integer(left.i << right.i);
}
const integer
operator>>(const integer& left,
		   const integer& right)
{
	return integer(left.i >> right.i);
}
integer&
operator+=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i += right.i;
	return left;
}
integer&
operator-=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i -= right.i;
	return left;
}
integer&
operator*=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i *= right.i;
	return left;
}
integer&
operator/=(integer& left,
		   const integer& right)
{
	allege(right.i != 0, "divide by zero");
	if(&left == &right)
	{
		//self-assignment
	}
	left.i /= right.i;
	return left;
}
integer&
operator%=(integer& left,
		   const integer& right)
{
	allege(right.i != 0, "modulo by zero");
	if(&left == &right)
	{
		//self-assignment
	}
	left.i %= right.i;
	return left;
}
integer&
operator^=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i ^= right.i;
	return left;
}
integer&
operator&=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i &= right.i;
	return left;
}
integer&
operator|=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i |= right.i;
	return left;
}
integer&
operator>>=(integer& left,
			const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i >>= right.i;
	return left;
}
integer&
operator<<=(integer& left,
			const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i <<= right.i;
	return left;
}
int operator==(const integer& left,
			   const integer& right)
{
	return left.i == right.i;
}
int operator!=(const integer& left,
			   const integer& right)
{
	return left.i != right.i;
}
int operator<(const integer& left,
			  const integer& right)
{
	return left.i < right.i;
}
int operator>(const integer& left,
			  const integer& right)
{
	return left.i > right.i;
}
int operator<=(const integer& left,
			   const integer& right)
{
	return left.i <= right.i;
}
int operator>=(const integer& left,
			   const integer& right)
{
	return left.i >= right.i;
}
int operator&&(const integer& left,
			   const integer& right)
{
	return left.i && right.i;
}
int operator||(const integer& left,
			   const integer& right)
{
	return left.i || right.i;
}

void h(integer& c1, integer& c2)
{
	c1 += c1 * c2 + c2 % c1;
#define TPY(op)	out << "c1 = "; c1.print(out);	out << ", c2 = "; c2.print(out);	out << "; c1 " #op " c2 produces ";	(c1 op c2).print(out);	out << endl;
	TPY(+) TPY(-) TPY(*) TPY(/)
	TPY(%) TPY(^) TPY(&) TPY(|)
	TPY(<<) TPY(>>) TPY(+=) TPY(-=)
	TPY(*=) TPY(/=) TPY(%=) TPY(^=)
	TPY(&=) TPY(|=) TPY(>>=) TPY(<<=)
#define TRYC(op)	out << "c1 = "; c1.print(out);	out << ", c2 = "; c2.print(out);	out << "; c1 " #op " c2 produces ";	out << (c1 op c2);	out << endl;
	TRYC(<) TRYC(>) TRYC(==) TRYC(!=) TRYC(<=)
	TRYC(>=) TRYC(&&) TRYC(||)
}

class byte
{
	unsigned char b;
public:
	byte(unsigned char B = 0):b(B){}
	const byte
		operator+(const byte& right) const
	{
		return byte(b + right.b);
	}
	const byte
		operator-(const byte& right) const
	{
		return byte(b - right.b);
	}
	const byte
		operator*(const byte& right) const
	{
		return byte(b * right.b);
	}
	const byte
		operator/(const byte& right) const
	{
		allege(right.b != 0, "divide by zero");
		return byte(b / right.b);
	}
	const byte
		operator%(const byte& right) const
	{
		allege(right.b != 0, "modulo by zero");
		return byte(b % right.b);
	}
	const byte
		operator^(const byte& right) const
	{
		return byte(b ^ right.b);
	}
	const byte
		operator&(const byte& right) const
	{
		return byte(b & right.b);
	}
	const byte
		operator|(const byte& right) const
	{
		return byte(b | right.b);
	}
	const byte
		operator<<(const byte& right) const
	{
		return byte(b << right.b);
	}
	const byte
		operator>>(const byte& right) const
	{
		return byte(b >> right.b);
	}
	byte& operator = (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b = right.b;
		return *this;
	}
	byte& operator += (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b += right.b;
		return *this;
	}
	byte& operator -= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b -= right.b;
		return *this;
	}
	byte& operator *= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b *= right.b;
		return *this;
	}
	byte& operator /= (const byte& right)
	{
		allege(right.b != 0, "divide by zero");
		if(this == &right)
		{
			return *this;
		}
		b /= right.b;
		return *this;
	}
	byte& operator %= (const byte& right)
	{
		allege(right.b != 0, "modulo by zero");
		if(this == &right)
		{
			return *this;
		}
		b %= right.b;
		return *this;
	}
	byte& operator ^= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b ^= right.b;
		return *this;
	}
	byte& operator &= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b &= right.b;
		return *this;
	}
	byte& operator |= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b |= right.b;
		return *this;
	}
	byte& operator >>= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b >>= right.b;
		return *this;
	}
	byte& operator <<= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b <<= right.b;
		return *this;
	}
	int operator == (const byte& right) const
	{
		return b == right.b;
	}
	int operator != (const byte& right) const
	{
		return b != right.b;
	}
	int operator < (const byte& right) const
	{
		return b < right.b;
	}
	int operator > (const byte& right) const
	{
		return b > right.b;
	}
	int operator <= (const byte& right) const
	{
		return b <= right.b;
	}
	int operator >= (const byte& right) const
	{
		return b >= right.b;
	}
	int operator && (const byte& right) const
	{
		return b && right.b;
	}
	int operator || (const byte& right) const
	{
		return b || right.b;
	}
	void print(ostream& os) const
	{
		os << "0x" << hex << int(b) << dec;
	}
};

void k(byte& b1, byte& b2)
{
	b1 = b1 * b2 + b2 % b1;
#define TRY2(op)	out << "b1 = "; b1.print(out);	out << ",b2 = "; b2.print(out);	out << "; b1 " #op "b2 produces ";	(b1 op b2).print(out);	out << endl;

	b1 = 9; b2 = 47;
	TRY2(+) TRY2(-) TRY2(*) TRY2(/)
	TRY2(%) TRY2(^) TRY2(&) TRY2(|)
	TRY2(<<) TRY2(>>) TRY2(+=) TRY2(-=)
	TRY2(*=) TRY2(/=) TRY2(%=) TRY2(^=)
	TRY2(&=) TRY2(|=) TRY2(>>=) TRY2(<<=)
	TRY2(=) 

#define TRYC2(op)	out << "b1 = "; b1.print(out);	out << ", b2 = "; b2.print(out);	out << "; b1 " #op " b2 prouduces ";	out << (b1 op b2);	out << endl;

	b1 = 9; b2 = 47;
	TRYC2(<) TRYC2(>) TRYC2(==) TRYC2(!=) TRYC2(<=)
	TRYC2(>=) TRYC2(&&) TRYC2(||)

	byte b3 = 92;
	b1 = b2 = b3;
}

int main()
{
	integer c1(47), c2(9);
	h(c1,c2);
	out << "\n member functions:" << endl;
	byte b1(47), b2(9);
	k(b1, b2);

	return 0;
}

4.

#include <iostream.h>

class after
{
public:
	const after& operator, (const after&) const
	{
		cout << "after::operator,()" << endl;
		return *this;
	}
};

class before{};

before& operator, (int, before& b)
{
	cout << "before::operator,()" << endl;
	return b;
}

int main()
{
	after a, b;
	a, b;

	before c;
	1, c;

	return 0;
}

5.

/*为了使一个对象的表现是一个指针,就要设计使用灵巧 ( smart )指针: ->。如果想为类包装
一个指针以使得这个指针安全 , 或是在一个普通的循环子(iterator)的用法中,则这样做特别
有用。循环子是一个对象,这个对象可以作用于其他对象的包容器或集合上,每次选择它们中
的一个,而不用提供对包容器实现的直接访问。(在类函数里经常发现包容器和循环子。)
灵巧指针必须是成员函数。它有一个附加的非典型的内容:它必须返回一个对象(或对象
的引用),这个对象也有一个灵巧指针或指针,可用于选择这个灵巧指针所指向的内容。*/
/*SMARTP.cpp*/
/*在main()中,一旦包容器OC装入obj对象,一个循环子SP就创建了。灵巧指针按下面的表
达式调用:
SP->f() ; //Smart pointer calls
SP->g() ;
这里,尽管SP实际上并不含成员函数f()和g(),但结构指针机制通过 obj*调用这些函数,
obj* 是通过sp::operator->返回的。编译器进行所有检查以确信函数调用正确。*/
#include <iostream.h>
#include <string.h>

class obj
{
	static int i, j;
public:
	void f()
	{
		cout << i++ << endl;
	}
	void g()
	{
		cout << j++ << endl;
	}
};

int obj::i = 47;
int obj::j = 11;

class obj_container
{
	enum{ sz = 100 };
	obj* a[sz];
	int index;
public:
	obj_container()
	{
		index = 0;
		memset(a, 0, sz * sizeof(obj*));
	}
	void add(obj* OBJ)
	{
		if(index >= sz)
		{
			return;
		}
		a[index++] = OBJ;
	}
	friend class sp;
};

class sp
{
	obj_container* oc;
	int index;
public:
	sp(obj_container* OC)
	{
		index = 0;
		oc = OC;
	}
	int operator++()
	{
		if(index >= oc->sz)
		{
			return 0;
		}
		if(oc->a[++index] == 0)
		{
			return 0;
		}
		return 1;
	}
	int operator++(int)
	{
		return operator++();
	}
	obj* operator->() const
	{
		if(oc->a[index])
		{
			return oc->a[index];
		}
		static obj dummy;
		return &dummy;
	}
};

int main()
{
	const sz = 10;
	obj o[sz];
	obj_container OC;
	for(int i = 0; i < sz; ++i)
	{
		OC.add(&o[i]);
	}
	sp SP(&OC);
	do{
		SP->f();
		SP->g();
	}while(SP++);

	return 0;
}

6.

/*IOSOP.cpp*/
//当左侧操作数是当前类的对象时,运算符会工作得很好。
//但也不完全是这种情况—有时我们左侧运算符是别的类对象。这种情况通常出现在为iostreams重载运算符<<和>>时候。
#include <iostream.h>
#include <strstrea.h>
#include <string.h>
#include "E:\VC++\7_31_2\allege.h"

class intarray
{
	enum{ sz = 5 };
	int i[sz];
public:
	intarray()
	{
		memset(i, 0, sz * sizeof(*i));
	}
	int& operator[](int x)
	{
		allege(x >= 0 && x < sz, "operator[] out of range");
		return i[x];
	}
	friend ostream&
		operator<<(ostream& os, const intarray& ia);
	friend istream&
		operator>>(istream& is, intarray& ia);
};

ostream& operator<<(ostream& os, const intarray& ia)
{
	for(int j = 0; j < ia.sz; ++j)
	{
		os << ia.i[j];
		if(j != ia.sz - 1)
		{
			os << ", ";
		}
	}
	os << endl;
	return os;
}
istream& operator>>(istream& is, intarray& ia)
{
	for(int j = 0; j < ia.sz; ++j)
	{
		is >> ia.i[j];
	}
	return is;
}

int main()
{
	istrstream input("47 34 56 92 103");
	intarray I;
	input >> I;
	I[4] = -1;
	cout << I;

	return 0;
}

7.

/*FEEFI.cpp*/
/*当创建一个运算符‘ =’时,必须从右侧对象中拷贝所有需要的信息完成为类的“赋值”,
对于单个对象,这是显然的*/
/*这个例子犯了一个普通的错误。当准备给两个相同类型的对象赋值时,应该首先检查一下
自赋值(self-assignment):这个对象是否对自身赋值了?在一些情况下,例如本例,无论如何执
行这些赋值运算都是无害的,但如果对类的实现作了修改,那么将会出现差异。如果我们习惯
于不做检查,就可能忘记并产生难以发现的错误。*/
#include <iostream.h>

class fi
{
	fi()
	{}
};

class fee
{
public:
	fee(int){}
	fee(const fi&){}
};

int main()
{
	fee f = 1;//fee(int)
	fi FI;
	fee fum = FI;//fee fum(FI);

	return 0;
}

8.

/*SIMPCOPY.cpp*/
#include <iostream.h>

class value
{
	int a, b;
	float c;
public:
	value(int A = 0, int B = 0, float C = 0.0)
	{
		a = A;
		b = B;
		c = C;
	}
	value& operator=(const value& rv)
	{
		a = rv.a;
		b = rv.b;
		c = rv.c;
		return *this;
	}
	friend ostream&
		operator<<(ostream& os, const value& rv)
	{
		return os << "a = " << rv.a << ", b = "
			<< rv.b << ", c = " << rv.c;
	}
};

int main()
{
	value A, B(1, 2, 3.3);
	cout << "A: " << A << endl;
	cout << "B: " << B << endl;
	A = B;
	cout << "A after assignment: " << A << endl;

	return 0;
}

9.

/*当我们做一个赋值运算或一个拷贝构造函数时,最简单的技
术是拷贝这个指针所涉及的一切*/
/*COPYMEM.cpp*/
#include <stdlib.h>
#include <string.h>
#include "E:\VC++\7_31_2\allege.h"

class withPointer
{
	char* p;
	enum{ blocksz = 100 };
public:
	withPointer()//普通构造函数
	{
		p = (char*)malloc(blocksz);
		allegemem(p);
		memset(p, 1, blocksz);
	}
	withPointer(const withPointer& wp)//拷贝构造函数
	{
		p = (char*)malloc(blocksz);
		allegemem(p);
		memcpy(p, wp.p, blocksz);
	}
	withPointer&
		operator=(const withPointer& wp)//运算符‘ =’(无论定义它还是不允许它)
	{
		if(&wp != this)
		{
			memcpy(p, wp.p, blocksz);
		}
		return *this;
	}
	~withPointer()//析构函数
	{
		free(p);
	}
};

int main()
{
	return 0;
}

10.

/*简单的引用记数和关于写拷贝*/
/*REFCOUNY.cpp*/
#include <string.h>
#include <assert.h>
#include <iostream.h>

class counted
{
	class memblock
	{
		enum{ size  = 100 };
		char c[size];
		int refcount;
	public:
		memblock()
		{
			memset(c, 1, size);
			refcount = -1;
		}
		memblock(const memblock& rv)
		{
			memcpy(c, rv.c, size);
			refcount = -1;
		}
		void attach()
		{
			++refcount;
		}
		void detach()
		{
			assert(refcount != 0);
			if(--refcount == 0)
			{
				delete this;
			}
		}
		int count() const
		{
			return refcount;
		}
		void set(char x)
		{
			memset(c, x, size);
		}
		memblock* unalias()// unalias()防止修改一个已别名化了的存储单元(超过一个对象使用的存储单元)
		{
			if(refcount == 1)
			{
				return this;
			}
			--refcount;
			return new memblock(*this);
		}
	}*block;
public:
	counted()
	{
		block = new memblock;
	}
	counted(const counted& rv)
	{
		block = rv.block;
		block->attach();
	}
	void unalias()
	{
		block = block->unalias();
	}
	counted& operator=(const counted& rv)
	{
		if(&rv == this)
		{
			return *this;
		}
		block->detach();
		block = rv.block;
		block->attach();
		return *this;
	}
	~counted()//析构函数调用detach( )有条件地销毁m e m b l o c k
	{
		block->detach();
	}
	void write(char value)//write()允许对这个存储单元修改数值
	{
		unalias();
		block->set(value);
	}
};

int main()
{
	counted A, B;//构造函数
	counted C(A);//拷贝构造函数
	B = A;//运算符‘ =’
	C = C;//运算符‘ =’
	C.write('x');//为对象C调用write()测试写拷贝

	return 0;
}

11.

/*对类增加信息和功能以便产生可被分析的跟踪
输出*/
/*RCTRACE.cpp*/

#include <string.h>
#include <fstream.h>
#include <assert.h>
#include <iostream.h>
ofstream out("rctrace.out");

class counted
{
	class memblock
	{
		enum{ size  = 100 };
		char c[size];
		int refcount;
		static int blockcount;//记录创建的存储单元号码
		int blocknum;//为了区分这些存储单元它还为每个存储单元创建了唯一号码(存放在blocknum中)
	public:
		memblock()
		{
			memset(c, 1, size);
			refcount = 1;
			blocknum = blockcount++;
		}
		memblock(const memblock& rv)
		{
			memcpy(c, rv.c, size);
			refcount = 1;
			blocknum = blockcount++;
			print("copied block");
			out << endl;
			rv.print("from block");
		}
		~memblock()
		{
			out << "\tdestroying block "
				<< blocknum << endl;
		}
		void print(const char* msg = "") const//print()函数显示块号和引用记数
		{
			if(*msg)
			{
				out << msg << ", ";
			}
			out << "blocknum:" << blocknum;
			out << ", refcount:" << refcount;
		}
		void attach()
		{
			++refcount;
		}
		void detach()
		{
			assert(refcount != 0);
			if(--refcount == 0)
			{
				delete this;
			}
		}
		int count() const
		{
			return refcount;
		}
		void set(char x)
		{
			memset(c, x, size);
		}
		memblock* unalias()// unalias()防止修改一个已别名化了的存储单元(超过一个对象使用的存储单元)
		{
			if(refcount == 1)
			{
				return this;
			}
			--refcount;
			return new memblock(*this);
		}
	}*block;
	enum{ sz  = 30 };
	char id[sz];//缓冲器 id用来记录对象信息
public:
	counted(const char* ID = "tmp")
	{
		block = new memblock;
		strncpy(id, ID, sz);
	}
	counted(const counted& rv)
	{
		block = rv.block;
		block->attach();
		strncpy(id, rv.id, sz);
		strncat(id, " copy", sz - strlen(id));
	}
	void unalias()
	{
		block = block->unalias();
	}
	void addname(const char* nm)
		//函数 addname()也让我们在id(这是实际的标识符,所以我们可以看到它是什么以及从哪里拷贝
		//来的)中加入有关对象的附加信息。
	{
		strncat(id, nm, sz - strlen(id));
	}
	counted& operator=(const counted& rv)
	{
		print("inside operator = \n\t");
		if(&rv == this)
		{
			out << "self-assignment" << endl;
			return *this;
		}
		block->detach();
		block = rv.block;
		block->attach();
		return *this;
	}
	~counted()//析构函数调用detach( )有条件地销毁m e m b l o c k
	{
		out << "preparing to destroy: " << id
			<< endl << "\tdecrementing refcount ";
		block->print();
		out << endl;
		block->detach();
	}
	void write(char value)//write()允许对这个存储单元修改数值
	{
		unalias();
		block->set(value);
	}
	void print(const char* msg = "")
	{
		if(*msg)
		{
			out << msg << " ";
		}
		out << "object "<< id << ": ";
		block->print();
		out << endl;
	}
};

int counted::memblock::blockcount = 0;

int main()
{
	counted A("A"), B("B");//构造函数
	counted C(A);//拷贝构造函数
	C.addname(" (C) ");
	A.print();
	B.print();
	C.print();
	B = A;//运算符‘ =’
	A.print("after assignment\n\t");
	B.print();
	out << "Assigning C = C" << endl;
	C = C;//运算符‘ =’
	C.print("calling C.write('x')\n\t");
	C.write('x');//为对象C调用write()测试写拷贝
	out << endl << "exiting main()" << endl;

	return 0;
}

12.

/*自动创建运算符‘=’
因为将一个对象赋给另一个相同类型的对象是大多数人可能做的事情,所以如果没有创建
type::operator=(type),编译器会自动创建一个。这个运算符行为模仿自动创建的拷贝构造函数
的行为:如果类包含对象(或是从别的类继承的),对于这些对象,运算符‘ =’被递归调用。
这被称为成员赋值(memberwise assignment)。*/
/*AUTOEQ.cpp*/
#include <iostream.h>

class bar
{
public:
	bar& operator=(const bar&)
	{
		cout << "inside bar::operator=()" << endl;
		return *this;
	}
};

class foo()
{
	bar B;
};
//为foo自动生成的运算符‘=’调用bar::operator=。
int main()
{
	foo a, b;
	a = b;

	return 0;
}

13.

/*构造函数转换*/
/*AUTOCNST.cpp*/
/*当编译器看到 f()以为对象one参数调用时,编译器检查 f()的声明并注意到它需要一个two
对象作为参数。然后,编译器检查是否有从对象 one 到two的方法。它发现了构造函数
two::two(one),two::two(one)被悄悄地调用,结果对象two被传递给f()。
在这个情况里,自动类型转换避免了定义两个 f()重载版本的麻烦。然而,代价是隐藏了
构造函数对two的调用,如果我们关心f()的调用效率的话,那就不要使用这种方法。*/
#include <iostream.h>

class one
{
public:
	one()
	{}
};

class two
{
public:
	two(const one&)
	{}
};

void f(two)
{}

int main()
{
	one One;
	f(One);

	return 0;
}

14.

/*阻止构造函数转换
有时通过构造函数自动转换类型可能出现问题。为了避开这个麻烦,可以通过在前面加关
键字explicit(只能用于构造函数)来修改构造函数*/
#include <iostream.h>

class one
{
public:
	one()
	{}
};

class two
{
public:
	explicit two(const one&)
	{}
};

void f(two)
{}

int main()
{
	one One;
	//!f(One);//no auto conversion allowed
	f(two(One));
	//上面代码f(two(One))创建一个从类型One到two的临时对象

	return 0;
}

15.

/*运算符转换
第二种自动类型转换的方法是通过运算符重载。我们可以创建一个成员函数,这个函数通
过在关键字 operator后跟随想要转换到的类型的方法,将当前类型转换为希望的类型。*/
/*OPCONV.cpp*/

#include <iostream.h>

class three
{
	int i;
public:
	three(int I = 0,int = 0):i(I){}
};

class four
{
	int x;
public:
	four(int X):x(X){}
	operator three() const
	{
		return three(x);
	}
};

void g(three)
{}

int main()
{
	four Four(1);
	g(Four);
	g(1);

	return 0;
}

16.

/* 反身性
使用全局重载运算符而不用成员运算符的最便利的原因之一是在全局版本中的自动类型转
换可以针对左右任一操作数,而成员版本必须保证左侧操作数已处于正确的形式。如果想两个
操作数都被转换,全局版本可以节省很多代码。*/
/*REFLEX.cpp*/
/*类number有一个成员运算符+号和一个友元(friend)运算符 - 号。因为有一个使用单一 int参
数的构造函数,int自动转换为number,但这要在正确的条件下。在 main()里,可以看到增加
一个number到另一个number进行得很好,这是因为它重载的运算符非常匹配。当编译器看到
一个number后跟一个+号和一个int时,它也能和成员函数 number::operator+相匹配并且构造函
数把int参数转换为number。但当编译器看到一个int、一个+号和一个number时,它就不知道如
何去做,因为它所拥有的是 number::operator+,需要左侧的操作数是 number对象。因此,编译
器发出一个出错信息。
对于友元运算符 -号,情况就不同了。编译器需要填满两个参数,它不限定 number作为左
侧参数。因此,如果看到表达式 1-a,编译器就使用构造函数把第一个参数转换为 number。有
时我们也许想通过把它们设成成员函数来限定运算符的使用。例如当用一个矢量与矩阵相乘,
矢量必须在右侧。但如果想让运算符转换任一个参数,就要使运算符为友元函数。
幸运的是编译器不会把表达式 1-1的两个参数转换为 number对象,然后调用运算符 - 号。
那将意味着现有的 C代码可能突然执行不同的工作了。编译器首先匹配“最简单的”可能性,
对于表达式1 - 1将优先使用内部运算符。*/
#include <iostream.h>

class number
{
	int i;
public:
	number(int I = 0)
	{
		i = I;
	}
	const number
		operator+(const number& n) const

	{
		return number(i + n.i);
	}
	friend const number
		operator-(const number&, const number&);
};

const number
		operator-(const number& n1,
		          const number& n2)
{
	return number(n1.i - n2.i);
}

int main()
{
	number a(47), b(11);
    a + b;//OK
	a + 1;//2nd arg converted to number
	//!1 + a;//Wrong!1st arg not of type number
	a - b;//OK
	a - 1;//2nd arg converted to number
	1 - a;//1st arg converted to number

	return 0;
}

17.

/*STRINGS1.cpp*/
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include "E:\VC++\7_31_2\allege.h"

class string
{
	char* s;
public:
	string(const char* S = "")
	{
		s = (char*)malloc(strlen(S) + 1);
		allegemem(s);
		strcpy(s, S);
	}
	~string()
	{
		free(s);
	}
	int Strcmp(const string& S) const
	{
		return ::strcmp(s, S.s);
	}
};

int main()
{
	string s1("hello"), s2("there");
	s1.Strcmp(s2);

	return 0;
}

18.

/*提供一个允许访问STRING.H中所有函数的自动类型转换*/
/*STRINGS2.cpp*/
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include "E:\VC++\7_31_2\allege.h"

class string
{
	char* s;
public:
	string(const char* S = "")
	{
		s = (char*)malloc(strlen(S) + 1);
		allegemem(s);
		strcpy(s, S);
	}
	~string()
	{
		free(s);
	}
	operator const char*() const
	//因为编译器知道如何从string转换到char*,所以现在任何一个接受 char*参数的函数也可以接受string参数。
	{
		return s;
	}
};

int main()
{
	string s1("hello"), s2("there");
	strcmp(s1, s2);
	strspn(s1, s2);

	return 0;
}

19.

/*编译器有两个从 X到Y的转换方法,所以发生转换时,编译器会产生一个不明确指示的出错信息*/
/*AMBIG.cpp*/
#include <iostream.h>

class Y;

class X
{
public:
	operator Y() const;
};

class Y
{
public:
	Y(X);
};

void f(Y);

int main()
{
	X x;
	//!f(x);//Error:ambiguous conversion

	return 0;
}

20.

/*提供自动转换到不止一种类型时,会引发更困难的问题。有时,这个问题被称为扇出*/
/*FANOUT.cpp*/
/*类C有向A和B的自动转换。这样存在一个隐藏的缺陷:使用创建的两种版本的重载运算符
h()时问题就出现了。(只有一个版本时, main()里的代码会正常运行。)
通常,对于自动类型的解决方案是只提供一个从一个类型向另一个类型转换的自动转换版
本。当然我们也可以有多个向其他类型的转换,但它们不应该是自动转换,而应该创建显式的
调用函数,例如用名字make_A()和make_B()表示这些函数。*/
#include <iostream.h>

class A{};
class B{};

class C
{
public:
	operator A() const;
	operator B() const;
};

void h(A);
void h(B);

int main()
{
	C c;
	//!h(c);//Error:C->A or C->B

	return 0;
}

21.

/*FEEFI2.cpp*/
/*这里没有从fo对象创建fee fiddle的构造函数。然而, fo有一个到fee的自动类型转换。这里
也没有从fee对象创建fee的拷贝构造函数,但这是一种能由编译器帮助我们创建的特殊函数之
一。(缺省的构造函数、拷贝构造函数、运算符‘ =’和析构函数可被自动创建)对于下面的声
明,自动类型转换运算符被调用并创建一个拷贝函数:
fee fiddle = FO ;
自动类型转换应该小心使用。它在减少代码方面是非常出色的,但不值得无缘无故地使
用。*/
#include <iostream.h>

class fi{};

class fee
{
public:
	fee(int){}
	fee(const fi&){}
};

class fo
{
	int i;
public:
	fo(int x = 0)
	{
		i = x;
	}
	operator fee() const
	{
		return fee(i);
	}
};

int main()
{
	fo FO;
	fee fiddle = FO;

	return 0;
}

二.习题+解答

1. 写一个有重载运算符++的类。试着用前缀和后缀两种形式调用此运算符,看看编译器会给我们什么警告。

#include <iostream.h>

class A
{
	int b;
public:
	A(int B = 0):b(B){}
	const A& operator++()//++b
	{
		cout << "++byte\n";
		b++;
		return *this;
	}
	const A operator++(int)//b++
	{
		cout << "byte++\n";
		A before(b);
		b++;
		return before;
	}
};

int main()
{
	A b;
	b++;
	++b;

	return 0;
}

此时运行正常

如下情况:

(1).

#include <iostream.h>

class A
{
	int b;
public:
	A(int B = 0):b(B){}
	const A& operator++()//++b
	{
		cout << "++byte\n";
		b++;
		return *this;
	}
};

int main()
{
	A b;
	b++;
	++b;

	return 0;
}

运行结果如下:

(2).

#include <iostream.h>

class A
{
	int b;
public:
	A(int B = 0):b(B){}
	const A operator++(int)//b++
	{
		cout << "byte++\n";
		A before(b);
		b++;
		return before;
	}
};

int main()
{
	A b;
	b++;
	++b;

	return 0;
}

运行结果:error C2675: unary ‘++‘ : ‘class A‘ does not define this operator or a conversion to a type acceptable to the predefined operator

2. 写一个只含有单个private char成员的类。重载iostream运算符<<和>>(像在IOSOP.CPP中的一样)并测试它们,可以用fstreams、strstreams和stdiostreams(cin和cout )测试它们。

#include <iostream.h>
#include <strstrea.h>
#include <fstream.h>
#include <stdio.h>

class B
{
	char c;
public:
	B(char c = '0')
	{}
	friend ostream&
		operator<<(ostream& os, const B& ic);
	friend istream&
		operator>>(istream& is, B& ic);
};

ostream& operator<<(ostream& os, const B& ic)
{
	os << ic.c;
	os << endl;
	return os;
}

istream& operator>>(istream& is, B& ic)
{
	is >> ic.c;
	return is;
}

int main()
{
	//stdiostreams
	B I;
	cin >> I;
	cout << I;
    //strstreams
	ostrstream os;
	B J;
	cin >> J;
    os << J << ends;
    char* s = os.str();
    cout << s << endl;
    os.rdbuf()->freeze(0);
	//fstreams
	istrstream input("a");
	B K;
	input >> K;
	cout << K;

	return 0;
}

3. 写一个包含重载的运算符+、- 、*、/和赋值符的number类。出于效率考虑,为这些函数合理地选择返回值以便以链式写表达式。写一个自动类型转换运算符 int()。

#include <fstream.h>
#include "E:\VC++\7_31_2\allege.h"

ofstream out("binary.out");

class number
{
	long i;
public:
	number(long I = 0):i(I){}
	number(int){}
	number& operator=(const number&)
	{
		cout << "inside number::operator=()" << endl;
		return *this;
	}
	friend const number
		operator+(const number& left,
		          const number& right);
	friend const number
		operator-(const number& left,
		          const number& right);
	friend const number
		operator*(const number& left,
		          const number& right);
	friend const number
		operator/(const number& left,
		          const number& right);
	void print(ostream& os) const
	{
		os << i;
	}
};

const number
operator+(const number& left,
		  const number& right)
{
	return number(left.i + right.i);
}
const number
operator-(const number& left,
		  const number& right)
{
	return number(left.i - right.i);
}
const number
operator*(const number& left,
		  const number& right)
{
	return number(left.i * right.i);
}
const number
operator/(const number& left,
		  const number& right)
{
	allege(right.i != 0,"divide by zero");
		return number(left.i / right.i);
}

class byte
{
	unsigned char b;
public:
	operator number() const
	{
		return number(b);
	}
	byte(unsigned char B = 0):b(B){}
	byte& operator=(const byte&)
	{
		cout << "inside byte::operator=()" << endl;
		return *this;
	}
	const byte
		operator+(const byte& right) const
	{
		return byte(b + right.b);
	}
	const byte
		operator-(const byte& right) const
	{
		return byte(b - right.b);
	}
	const byte
		operator*(const byte& right) const
	{
		return byte(b * right.b);
	}
	const byte
		operator/(const byte& right) const
	{
		allege(right.b != 0, "divide by zero");
		return byte(b / right.b);
	}
	void print(ostream& os) const
	{
		os << "0x" << hex << int(b) << dec;
	}
};

int main()
{
	number c1(47), c2(9);
	out << "\n member functions:" << endl;
	byte b1(47), b2(9);
	number fiddle = b1;

	return 0;
}

4. 合并在UNARY.CPP和BINARY. CPP中的类。

#include <iostream.h>
#include <fstream.h>
#include "E:\VC++\7_31_2\allege.h"
ofstream out("binary.out");

class integer
{
	long i;
	integer* This()
	{
		return this;
	}
public:
	integer(long I = 0):i(I)
	{}
	friend const integer&
		operator+(const integer& a);
	friend const integer
		operator-(const integer& a);
	friend const integer
		operator~(const integer& a);
	friend integer*
		operator&(integer& a);
	friend int
		operator!(const integer& a);
	friend const integer&
		operator++(integer& a);//++a
	friend const integer
		operator++(integer& a, int);//a++
	friend const integer&
		operator--(integer& a);//--a
	friend const integer
		operator--(integer& a, int);//a--
	friend const integer
		operator+(const integer& left,
		          const integer& right);
	friend const integer
		operator-(const integer& left,
		          const integer& right);
	friend const integer
		operator*(const integer& left,
		          const integer& right);
	friend const integer
		operator/(const integer& left,
		          const integer& right);
	friend const integer
		operator%(const integer& left,
		          const integer& right);
	friend const integer
		operator^(const integer& left,
		          const integer& right);
	friend const integer
		operator&(const integer& left,
		          const integer& right);
	friend const integer
		operator|(const integer& left,
		          const integer& right);
	friend const integer
		operator<<(const integer& left,
		          const integer& right);
	friend const integer
		operator>>(const integer& left,
		          const integer& right);
	friend integer&
		operator+=(integer& left,
		           const integer& right);
	friend integer&
		operator-=(integer& left,
		           const integer& right);
	friend integer&
		operator*=(integer& left,
		           const integer& right);
	friend integer&
		operator/=(integer& left,
		           const integer& right);
	friend integer&
		operator%=(integer& left,
		           const integer& right);
	friend integer&
		operator^=(integer& left,
		           const integer& right);
	friend integer&
		operator&=(integer& left,
		           const integer& right);
	friend integer&
		operator|=(integer& left,
		           const integer& right);
	friend integer&
		operator>>=(integer& left,
		           const integer& right);
	friend integer&
		operator<<=(integer& left,
		           const integer& right);
	friend int
		operator==(const integer& left,
		           const integer& right);
	friend int
		operator!=(const integer& left,
		           const integer& right);
	friend int
		operator<(const integer& left,
		           const integer& right);
	friend int
		operator>(const integer& left,
		           const integer& right);
		friend int
		operator<=(const integer& left,
		           const integer& right);
	friend int
		operator>=(const integer& left,
		           const integer& right);
		friend int
		operator&&(const integer& left,
		           const integer& right);
	friend int
		operator||(const integer& left,
		           const integer& right);
	void print(ostream& os) const
	{
		os << i;
	}
};

const integer& operator+(const integer& a)
{
	cout << "+integer\n";
	return a;
}

const integer operator-(const integer& a)
{
	cout << "-integer\n";
	return integer(-a.i);
}

const integer operator~(const integer& a)
{
	cout << "~integer\n";
	return integer(~a.i);
}

integer* operator&(integer& a)
{
	cout << "&integer\n";
	return a.This();
}

int operator!(const integer& a)
{
	cout << "!integer\n";
	return !a.i;
}

const integer& operator++(integer& a)
{
	cout << "++integer\n";
	a.i++;
	return a;
}

const integer operator++(integer& a, int)
{
	cout << "integer++\n";
	integer r(a.i);
	a.i++;
	return r;
}

const integer& operator--(integer& a)
{
	cout << "--integer\n";
	a.i--;
	return a;
}

const integer operator--(integer& a, int)
{
	cout << "integer--\n";
	integer r(a.i);
	a.i--;
	return r;
}

void f(integer a)
{
	+a;
	-a;
	~a;integer* ip = &a;
	!a;
	++a;
	a++;
	--a;
	a--;
}
const integer
operator+(const integer& left,
		  const integer& right)
{
	return integer(left.i + right.i);
}
const integer
operator-(const integer& left,
		  const integer& right)
{
	return integer(left.i - right.i);
}
const integer
operator*(const integer& left,
		  const integer& right)
{
	return integer(left.i * right.i);
}
const integer
operator/(const integer& left,
		  const integer& right)
{
	allege(right.i != 0,"divide by zero");
		return integer(left.i / right.i);
}
const integer
operator%(const integer& left,
		  const integer& right)
{
	allege(right.i != 0, "modulo by zero");
	return integer(left.i % right.i);
}
const integer
operator^(const integer& left,
		  const integer& right)
{
	return integer(left.i ^ right.i);
}
const integer
operator&(const integer& left,
		  const integer& right)
{
	return integer(left.i & right.i);
}
const integer
operator|(const integer& left,
		  const integer& right)
{
	return integer(left.i | right.i);
}
const integer
operator<<(const integer& left,
		   const integer& right)
{
	return integer(left.i << right.i);
}
const integer
operator>>(const integer& left,
		   const integer& right)
{
	return integer(left.i >> right.i);
}
integer&
operator+=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i += right.i;
	return left;
}
integer&
operator-=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i -= right.i;
	return left;
}
integer&
operator*=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i *= right.i;
	return left;
}
integer&
operator/=(integer& left,
		   const integer& right)
{
	allege(right.i != 0, "divide by zero");
	if(&left == &right)
	{
		//self-assignment
	}
	left.i /= right.i;
	return left;
}
integer&
operator%=(integer& left,
		   const integer& right)
{
	allege(right.i != 0, "modulo by zero");
	if(&left == &right)
	{
		//self-assignment
	}
	left.i %= right.i;
	return left;
}
integer&
operator^=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i ^= right.i;
	return left;
}
integer&
operator&=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i &= right.i;
	return left;
}
integer&
operator|=(integer& left,
		   const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i |= right.i;
	return left;
}
integer&
operator>>=(integer& left,
			const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i >>= right.i;
	return left;
}
integer&
operator<<=(integer& left,
			const integer& right)
{
	if(&left == &right)
	{
		//self-assignment
	}
	left.i <<= right.i;
	return left;
}
int operator==(const integer& left,
			   const integer& right)
{
	return left.i == right.i;
}
int operator!=(const integer& left,
			   const integer& right)
{
	return left.i != right.i;
}
int operator<(const integer& left,
			  const integer& right)
{
	return left.i < right.i;
}
int operator>(const integer& left,
			  const integer& right)
{
	return left.i > right.i;
}
int operator<=(const integer& left,
			   const integer& right)
{
	return left.i <= right.i;
}
int operator>=(const integer& left,
			   const integer& right)
{
	return left.i >= right.i;
}
int operator&&(const integer& left,
			   const integer& right)
{
	return left.i && right.i;
}
int operator||(const integer& left,
			   const integer& right)
{
	return left.i || right.i;
}

void h(integer& c1, integer& c2)
{
	c1 += c1 * c2 + c2 % c1;
#define TPY(op)	out << "c1 = "; c1.print(out);	out << ", c2 = "; c2.print(out);	out << "; c1 " #op " c2 produces ";	(c1 op c2).print(out);	out << endl;
	TPY(+) TPY(-) TPY(*) TPY(/)
	TPY(%) TPY(^) TPY(&) TPY(|)
	TPY(<<) TPY(>>) TPY(+=) TPY(-=)
	TPY(*=) TPY(/=) TPY(%=) TPY(^=)
	TPY(&=) TPY(|=) TPY(>>=) TPY(<<=)
#define TRYC(op)	out << "c1 = "; c1.print(out);	out << ", c2 = "; c2.print(out);	out << "; c1 " #op " c2 produces ";	out << (c1 op c2);	out << endl;
	TRYC(<) TRYC(>) TRYC(==) TRYC(!=) TRYC(<=)
	TRYC(>=) TRYC(&&) TRYC(||)
}

class byte
{
	unsigned char b;
public:
	byte(unsigned char B = 0):b(B){}
	const byte& operator+() const
	{
		cout << "+byte\n";
		return *this;
	}
	const byte operator-() const
	{
		cout << "-byte\n";
		return byte(-b);
	}
	const byte operator~() const
	{
		cout << "~byte\n";
		return byte(~b);
	}
	byte operator!() const
	{
		cout << "!byte\n";
		return byte(!b);
	}
	byte* operator&()
	{
		cout << "&byte\n";
		return this;
	}
	const byte& operator++()//++b
	{
		cout << "++byte\n";
		b++;
		return *this;
	}
	const byte operator++(int)//b++
	{
		cout << "byte++\n";
		byte before(b);
		b++;
		return before;
	}
	const byte& operator--()//--b
	{
		cout << "--byte\n";
		--b;
		return *this;
	}
	const byte operator--(int)//b--
	{
		cout << "byte--\n";
		byte before(b);
		--b;
		return before;
	}
	const byte
		operator+(const byte& right) const
	{
		return byte(b + right.b);
	}
	const byte
		operator-(const byte& right) const
	{
		return byte(b - right.b);
	}
	const byte
		operator*(const byte& right) const
	{
		return byte(b * right.b);
	}
	const byte
		operator/(const byte& right) const
	{
		allege(right.b != 0, "divide by zero");
		return byte(b / right.b);
	}
	const byte
		operator%(const byte& right) const
	{
		allege(right.b != 0, "modulo by zero");
		return byte(b % right.b);
	}
	const byte
		operator^(const byte& right) const
	{
		return byte(b ^ right.b);
	}
	const byte
		operator&(const byte& right) const
	{
		return byte(b & right.b);
	}
	const byte
		operator|(const byte& right) const
	{
		return byte(b | right.b);
	}
	const byte
		operator<<(const byte& right) const
	{
		return byte(b << right.b);
	}
	const byte
		operator>>(const byte& right) const
	{
		return byte(b >> right.b);
	}
	byte& operator = (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b = right.b;
		return *this;
	}
	byte& operator += (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b += right.b;
		return *this;
	}
	byte& operator -= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b -= right.b;
		return *this;
	}
	byte& operator *= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b *= right.b;
		return *this;
	}
	byte& operator /= (const byte& right)
	{
		allege(right.b != 0, "divide by zero");
		if(this == &right)
		{
			return *this;
		}
		b /= right.b;
		return *this;
	}
	byte& operator %= (const byte& right)
	{
		allege(right.b != 0, "modulo by zero");
		if(this == &right)
		{
			return *this;
		}
		b %= right.b;
		return *this;
	}
	byte& operator ^= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b ^= right.b;
		return *this;
	}
	byte& operator &= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b &= right.b;
		return *this;
	}
	byte& operator |= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b |= right.b;
		return *this;
	}
	byte& operator >>= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b >>= right.b;
		return *this;
	}
	byte& operator <<= (const byte& right)
	{
		if(this == &right)
		{
			return *this;
		}
		b <<= right.b;
		return *this;
	}
	int operator == (const byte& right) const
	{
		return b == right.b;
	}
	int operator != (const byte& right) const
	{
		return b != right.b;
	}
	int operator < (const byte& right) const
	{
		return b < right.b;
	}
	int operator > (const byte& right) const
	{
		return b > right.b;
	}
	int operator <= (const byte& right) const
	{
		return b <= right.b;
	}
	int operator >= (const byte& right) const
	{
		return b >= right.b;
	}
	int operator && (const byte& right) const
	{
		return b && right.b;
	}
	int operator || (const byte& right) const
	{
		return b || right.b;
	}
	void print(ostream& os) const
	{
		os << "0x" << hex << int(b) << dec;
	}
};

void g(byte b)
{
	+b;
	-b;
	~b;
	byte* bp = &b;
	!b;
	++b;
	b++;
	--b;
	b--;
}

void k(byte& b1, byte& b2)
{
	b1 = b1 * b2 + b2 % b1;
#define TRY2(op)	out << "b1 = "; b1.print(out);	out << ",b2 = "; b2.print(out);	out << "; b1 " #op "b2 produces ";	(b1 op b2).print(out);	out << endl;

	b1 = 9; b2 = 47;
	TRY2(+) TRY2(-) TRY2(*) TRY2(/)
	TRY2(%) TRY2(^) TRY2(&) TRY2(|)
	TRY2(<<) TRY2(>>) TRY2(+=) TRY2(-=)
	TRY2(*=) TRY2(/=) TRY2(%=) TRY2(^=)
	TRY2(&=) TRY2(|=) TRY2(>>=) TRY2(<<=)
	TRY2(=) 

#define TRYC2(op)	out << "b1 = "; b1.print(out);	out << ", b2 = "; b2.print(out);	out << "; b1 " #op " b2 prouduces ";	out << (b1 op b2);	out << endl;

	b1 = 9; b2 = 47;
	TRYC2(<) TRYC2(>) TRYC2(==) TRYC2(!=) TRYC2(<=)
	TRYC2(>=) TRYC2(&&) TRYC2(||)

	byte b3 = 92;
	b1 = b2 = b3;
}

int main()
{
	integer a;
	f(a);
	byte b;
	g(b);
	integer c1(47), c2(9);
	h(c1,c2);
	out << "\n member functions:" << endl;
	byte b1(47), b2(9);
	k(b1, b2);

	return 0;
}

5. 对FANOUT.CPP作如下修改:创建一个显式函数,用它代替自动转换运算符来完成类型转换。

自动类型转换:a.构造函数转换  b.运算符转换。

#include <iostream.h>

class A{};
class B{};

class C
{
public:
	C(){}
	C(const A&){}
	C(const B&){}
};

void f(C){}

int main()
{
	C c;
	f(c);

	return 0;
}

以上代码仅供参考,如有错误请大家指出,谢谢大家~

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-08 06:34:23

《C++编程思想》 第十一章 运算符重载 (习题+解答)的相关文章

第十一章 运算符重载

第十一章 运算符重载 1.  运算符重载 2.  在成员函数中实现自加 3.  重载前置自加运算符 返回类型 [email protected](参数表){} @代表要重载的运算符 对象运算符重载不同于变量运算符重载 void operator++(){++n;} ++i;//等价于i.operator++();若i是变量 则++i就是调用operator++() //n=++i;错误原因:右值为一个无符号的返回型 //1+2;等价于operator+(1+2),此时 4.  创建临时对象 见程

Java编程思想(第十一章持有对象)

1. 第11章 持有对象 java通过使用容器类来储存对象,与普通数组不同的是,普通数组的长度不可变. 1.1. 泛型与类型安全的容器 使用预定义的泛型,它指定了这个容器实例可以保存的类型,通过使用泛型,就可以在编译器防止将错误类型的对象放置到容器中. public class gerbil { private int gerbilNumber; public gerbil(int gerbilNumber){ this.gerbilNumber = gerbilNumber; } public

java编程思想笔记(第一章)

Alan Kay 第一个定义了面向对象的语言 1.万物皆对象 2.程序是对象的集合,他们彼此通过发送消息来调用对方. 3.每个对象都拥有由其他对象所构成的存储 4.每个对象都拥有其类型(TYpe) 5.某一特定类型的所有对象都可以接收同样的消息. Booch提出一种更简洁的描述: 对象拥有状态(state) 行为(behavior) 和标识(identity) 每个对象都有一个接口 每个对象都属于定义了特性和行为的某个类(特性可以理解为属性的状态,行为可以理解为method) 在面向对象的程序设

Java编程思想——第17章 容器深入研究(two)

六.队列 排队,先进先出.除并发应用外Queue只有两个实现:LinkedList,PriorityQueue.他们的差异在于排序而非性能. 一些常用方法: 继承自Collection的方法: add 在尾部增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常 remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常 element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementExce

sdut 面向对象程序设计上机练习十一(运算符重载)

面向对象程序设计上机练习十一(运算符重载) Time Limit: 1000MS Memory limit: 65536K 题目描述 有两个矩阵a和b,均为2行3列,求两个矩阵之和.重载运算符"+",使之能用于矩阵相加.如:c=a+b. 输入 第1.2行是矩阵a的值,数据以空格分开. 第3.4行是矩阵b的值,数据以空格分开. 输出 2个矩阵a.b之和,以行列形式显示. 示例输入 2 3 4 3 5 3 4 3 1 5 4 3 示例输出 6 6 5 8 9 6 来源 #include &

面向对象程序设计上机练习十一(运算符重载)

面向对象程序设计上机练习十一(运算符重载) Time Limit: 1000MS Memory limit: 65536K 题目描述 有两个矩阵a和b,均为2行3列,求两个矩阵之和.重载运算符“+”,使之能用于矩阵相加.如:c=a+b. 输入 第1.2行是矩阵a的值,数据以空格分开. 第3.4行是矩阵b的值,数据以空格分开. 输出 2个矩阵a.b之和,以行列形式显示. 示例输入 2 3 4 3 5 3 4 3 1 5 4 3 示例输出 6 6 5 8 9 6 #include <iostream

Java编程思想笔记(第二章)

第二章  一切都是对象 尽管Java是基于C++的,但相比之下,Java是一种更纯粹的面向对象程序设计语言. c++和Java都是杂合型语言(hybird language) 用引用(reference)操作对象 类似遥控器(引用)来操作电视(对象) 在Java中你可以创建一个引用,但是没有与任何对象关联,比如: String s; 这个时候如果用则会报错.安全的做法是: 创建一个引用的同时并进行初始化 String s="1111"; 必须由你创建所有对象 New关键字的意思是给我一

《Python核心编程》 第五章 数字 - 课后习题

课后习题  5-1 整形. 讲讲 Python 普通整型和长整型的区别. 答:普通整型是绝大多数现代系统都能识别的. Python的长整型类型能表达的数值仅仅与你机器支持的(虚拟)内存大小有关. 5-2 运算符 (a) 写一个函数,计算并返回两个数的乘积 (b) 写一段代码调用这个函数,并显示它的结果 答: def pro(a,b): p = a*b return p a = int(raw_input("a=")) b = int(raw_input("b="))

《C++编程思想》 第九章 命 名 控 制 (知识点+习题+解答)

一.相关知识点         那些通常放在头文件里的名字,像常量.内联函数(inline function),在缺省情况下都是内部连接的(当然常量只有在C + +中缺省情况下是内部连接的,在 C中它缺省为外部连接).注意连接只引用那些在连接/装载期间有地址的成员,因此类声明和局部变量并没有连接. 名字空间的产生与一个类的产生非常相似: namespace MyLib{ //Declarations } 这就产生了一个新的名字空间,其中包含了各种声明.namespace与class.struct