一、运算符重载
扩展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;
}