C++程序设计视频北大25-30(运算符重载)

一、运算符重载

扩展C++中提供的运算符适用范围,以用于所表示的抽象数据类型

运算符重载实质函数重载

运算符重载是成员函数时,a+b的 a.operator+b,a 相当于对象,只传入后面的参数

class A
{
public:
	A(double r = 0.0, double i = 0.0) :real(r), imag(m) {};//构造函数,初始值列表
	A operator+ (const A &b)//运算符重载为成员函数,参数个数为运算符个数减一
};

A operator+ (const A &a, const A &b)//运算符重载为普通函数,参数个数为运算符目数
{
	return A(a.real + b.real, a.imag + b.imag);
}

A A::operator+ (const A &b)//定义成员函数,运算符重载为成员函数
{
	return A(real + b.real, imag + b.imag);
}

A a(1, 2), b(2, 3), c;
c = a + b;//调用了operator+ (a,b)


class Box
{
	Box operator+(const Box &b)//重载运算符为成员函数
	{
		Box box;
		box.length = this->length + b.length;
		box.height = this->height + b.height;
		return box;
	}
};

int main()
{
	Box3 = Box1 + Box2;
}


二、赋值运算符重载

赋值运算符两边的类型可能不匹配,需要重载赋值运算符 '=',且只能重载成员函数

class string
{
private:
	char *str;//成员变量,char *类型,指向动态分配的存储空间
public:
	string() :str(NULL) {}//无参构造函数,初始化str为NULL
	const char *c_str() { return str; }//const,不能修改内容,返回指针
	char *operator=(const char *s);////赋值构造函数为成员函数
	~string();//析构函数
};

char *string::operator=(const char *s)//定义赋值构造函数,const只能利用指针读取不能修改
{
	if (str) delete[] str;//如果已经指向某个地址,需要delete掉
	if (s)//s不为NULL才会执行拷贝
	{
		str = new char[strlen(s) + 1];//重新分配空间
		strcpy(str, s);
	}
	else
		str = NULL;
	return str;
}

string::~string()//定义析构函数
{
	if (str) delete[] str;//判断str不为空才delete
}

int main()
{
	string s;
	s = "good look";//使用了赋值构造函数s.operator=("")
	//string s="good look" 错误,初始化语句而非赋值语句
	cout << s.c_str() << endl;
	return 0;
}

浅拷贝:逐个字节复制工作,s1=s2  s1.str与s2.str都指向that所在空间,释放两次,出问题。


深拷贝:只是拷贝,不影响自身


在class string 中添加成员函数

string &operator=(const string &s)
{
	if (str) delete[]str;
	str = new char[strlen(s.str) + 1];
	strcpy(str, s.str);
	return *this;
}


三、运算符重载为友元函数友元函数不是成员函数,定义在类外部

运算符重载通常为类的成员函数。

重载为友元函数:成员函数不能满足使用要求;普通函数不能访问类的私有成员

c=c+5 相当于c=c.operator+5

c=5+c  报错,

需要将+重载为普通函数  A operator+ (double r, const A &c)    return  A(c.real+r,c.imag)

但普通函数不能访问私有成员,需要声明为友元函数

friend  A operator+ (double r, const A &c)


四、流插入和提取运算符的重载

cout 是在iostream中定义的,ostream类的对象,不可能在这个类里面进行修改,只能定义普通全局函数

“‘<<"能用在cout上因为,在iostream里对"<<"进行了重载
我们需要把运算符重载函数声明为类的友元函数,这样我们就能不用创建对象而直接调用函数。

cout<<5<<"this"

ostream & ostream::operator<<(int n)
{
	return *this;
}


本质上cout.operator<<(5).operator<<("this");重载左移运算符

例题:输出5hello

class student
{
public:
	int age;
};
int main()
{
	student s;
	s.age = 5;
	cout << s << "hello";//要重载左移运算符
	return 0;
}
解答:
ostream &operator<<(ostream &o, const student &s)//o等价于cout的引用
{
	o << s.age;
	return o;
}

例题:cout<<c 就能以“a+bi"的形式输出c 的值且 c.real=a, c,imag=b

int main()
{
	A c;
	int n;
	cin >> c >> n;
	cout << c << "," << n;//实部和虚部分开写出来
	return 0;
}

解答:

class A
{
	double real, imag;//私有的
public:
	A(double r = 0, double i = 0) :real(r), imag(i) {};//构造函数初始化列表
	friend ostream & operator<<(ostream &os, const A &c);//友元函数,需要访问私有变量
	friend istream & operator>>(istream &is, const A &c);//友元函数,需要访问私有变量
};

ostream & operator << (ostream &os, const A &c)
{
	os << c.real << "+" << c.imag << "i";//以a+bi形式输出
	return os;
}

istream & operator>>(istream &is, const A &c)
{
	string s;
	is >> s;//将a+bi作为字符串读入
	int pos = s.find("+", 0);
	*****
		return is;
}







猜你喜欢

转载自blog.csdn.net/try_again_later/article/details/79923375