赞
踩
对抽象数据类型也能够直接使用C++提供的运算符,程序更简洁,代码更容易理解
对已有的运算符赋予多重的含义
目的:扩展C++中提供的运算符的适用范围,以用于类所表示的抽象数据类型
运算符重载的实质是函数重载
返回值类型 operator 运算符 (形参表)
{
...
}
运算符可以被重载成普通函数,也可以被重载成类的成员函数
重载为普通函数时,参数个数为运算符目数
Complex operator+(const Complex &a, const Complex &b) {
return Complex(a.real + b.real, a.imaginary + b.imaginary);
}
重载为成员函数时,参数个数为运算符目数减一
class Complex {
Complex operator+(const Complex &);
};
赋值运算符两边的类型可以不匹配
赋值运算符=
只能重载为成员函数
class String { private: char *str; public: String(): str(NULL){} const char *c_str() {return str;} char *operator=(const char *s); ~String(); }; char *String::operator=(const char *s) { // s.operator=("..."); if (str) delete []str; if (s) { str = new char[strlen(s) + 1]; strcpy(str, s); } else str = NULL; return str; } String S1, S2; S1 = "this"; S2 = "that";
浅复制/浅拷贝,执行逐个字节的复制工作
深复制/深拷贝,将一个对象中指针变量指向的内容,复制到另一个对象中指针成员对象指向的地方
String &String::operator=(const String &s) {
// s = s?
if (str == s.str) return *this; // 必须要考虑
if (str) delete[] str;
if (s.str) {
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
} else
str = NULL;
return *this;
}
S1 = S2;
返回值类型为void好不好?考虑a = b = c的情况
a.operator= (b.operator=(c));
String好不好,为什么是String&
运算符重载时,好的风格——尽量保留运算符原本的特性
(a = b) = c;
(a.operator= (b)).operator= (c);
为String类编写复制构造函数时,会面临和=
同样的问题,用同样的方法处理
String::String (String &s) {
if (s.str) {
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
} else
str = NULL;
}
重载为友元函数的情况:成员函数不能满足使用要求,普通函数又不能访问类的私有成员
c = c + 5;
c = 5 + c;
class Complex {
friend Complex operator+(double r, const Complex &c);
};
Complex operator+(double r, const Complex &c); // 普通函数不能访问私有成员
class CArray { int size; int *ptr; public: CArray (int s = 0); CArray (CArray &a); ~CArray(); void push_back(int v); // 用于在数组尾部添加一个元素 CArray &operator=(const CArray &a); // 用于数组对象之间的赋值 int length(); int &CArray::operator[](int i) { return ptr[i]; } // n = a[i]; 返回值不能为int,否则不支持a[i] = 4; }; CArray::CArray(int s): size(s) { if (s == 0) ptr = NULL; else ptr = new int[s]; } CArray::CArray(CArray &a) { // 深拷贝 if (!a.ptr) { ptr = NULL; size = 0; return; } ptr = new int[a.size]; memcpy(ptr, a.ptr, sizeof(int) * size); size = a.size; } CArray::~CArray() { if (ptr) delete []ptr; } CArray &CArray::operator=(const CArray &a){ // 深拷贝,注意返回值类型 if (ptr == a.ptr) // 防止a=a; return *this; if (a.ptr == NULL) { if (ptr) delete []ptr; ptr = NULL; size = 0; return *this; } if (size < a.size) { // 如果原有空间够大,就不用分配新的空间 if (ptr) delete [] ptr; ptr = new int[a.size]; } memcpy(ptr, a.ptr, sizeof(int) * a.size); size = a.size; return *this; } void CArray::push_back(int v) { // 低效 if (ptr) { int *tmpPtr = new int[size + 1]; memcpy(tmpPtr, ptr, sizeof(int) * size); delete [] ptr; ptr = tmpPtr; } else ptr = new int[1]; ptr[size++] = v; }
memcpy
vector
cout是在iostream中定义的,ostream类的对象。<<
能用在cout
上是因为在iostream
中对<<
进行了重载
// 重载成ostream类的成员函数 // cout << 5 << "this"; // 调用形式 cout.operator<<(5).operator<<("this"); ostream &ostream::operator<<(int n) { ... return *this; } // 这里只能重载成全局的函数,不能重载成ostream的成员函数 ostream &operator<<(ostream &o, const CStudent &s) { // o引用了cout,如果不是引用,编译不过? // friend o << s.nAge; return o; } #include<iostream> #include<string> #include<cstdlib> class Complex { double real, imag; public: Complex(double r = 0,double i = 0):real(r), imag(i){} friend ostream &operator<<(ostream &os, const Complex &c); friend istrema &operator>>(istream &is, Complex &c); } ostream &operator<<(ostream &os, const Complex &c) { os << c.real << "+" << c.imag << "i"; return os; } istream &operator>>(istream &is, Complex &c) { string s; is >> s; int pos = s.find("+", 0); string sTmp = s.substr(0, pos); c.real = atof(sTmp.c_str()); sTmp = s.substr(pos + 1, s.length() - pos - 2); c.imag = atof(sTmp.c_str()); return is; }
strcpy
warning C4996: ‘strcpy’: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
前置运算符(++i)作为一元运算符重载
重载为成员函数
T &operator++();
T &operator--();
重载为全局函数
T &operator++(T&);
T &operator--(T&);
++obj, obj.operator++(), operator++(obj)都调用上述函数
后置运算符(i++)作为二元运算符重载,多写一个参数,具体无意义
重载为成员函数
T &operator++(int);
T &operaotr–(int);
重载为全局函数
T &operator++(T&, int);
T &operator–(T&, int);
obj++, obj.operator++(0), operator++(obj, 0)都调用上述函数
operator int() {return n; }
int作为一个类型强制转换运算符被重载
Demo s;
(int) s; // <==> s.int()
cout << s; // cout << (int)s; ???
类型强制转换运算符重载时,不能写返回值类型,实际上其返回值类型–类型强制转换运算符代表的类型
C++不允许定义新的运算符
重载后运算符的含义应该符合日常习惯
运算符重载不改变运算符的优先级
以下运算符不能被重载:
.
.*
::
?:
sizeof
重载运算符()
[]
->
或者复制运算符=
时,重载函数必须声明为类的成员函数
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。