huangfu Blog
Love Leanote!
Toggle navigation
huangfu Blog
主页
About Me
归档
标签
08单目运算符重载/运算符重载的限制/特殊运算符重载
2017-02-16 16:12:07
167
0
0
tarena
#单目运算符重载 !(取反) ~(按位取反) -(负) ++(自增) --(自减号) >`#0` 默认操作符在前 操作数在后 先去0对象对应的类型中找一个成员函数叫`operator#()` 如果找不到就去全局找一个全局函数`operator#(0)` `0#` 默认操作符在前 操作数在后(`典型后减减和后加加`) 先去0对象对应的类型中找一个成员函数叫`operator#(int)` 如果找不到就去全局找一个全局函数`operator#(0, int)` ##列子代码 #include <iostream> using namespace std; class Idata { int data; public: Idata(int data):data(data) { } bool operator!() { return !data; } Idata operator-() { /* 单参构造*/ return -data; } Idata& operator++() { data++; return *this; } Idata operator++(int) { return data++; } friend ostream& operator<<(ostream& os, const Idata& a) { return os << a.data; } friend istream& operator>>(istream& is, Idata& a) { return is >> a.data; } }; int main() { Idata da(10); cout << !da << endl; cout << !!da << endl; cout << -da << endl; cout << -(-da) << endl; cout << ++da << endl; cout << ++++da << endl; cout << da++ << endl; cout << da << endl; } 扩展: > C语言和C++函数的返回值都是默认只读的,所以不能当做左值. 但是C++有一个BUG,如果C++中函数的返回值是类类型,可以赋值被干掉 Integer getData(); getData = a; // 编译能通过 所以C++代码要习惯性的在类类型返回值前加const `个人理解` 函数的返回值临时变量一般放入EAX(X86系统)寄存器,该寄存器需然可以可读可写 但是编译器会保护它,不让高级语言来对EXA寄存器中做写入操作,所以往临时区赋值编译报错 #运算符重载的限制 ##1. 不是所有的运算符都能重载 * :: 作用域运算符 * . 成员访问运算符 * .* 成员指针解引用运算符 * sizeof运算符 * ? : 三目运算符 * typeid 类型信息运算符 ##2. 只能对已经有的运算符重载 不能发明一运算符进行重载 ##3. 不能对基本类型进行运算符重载 运算符重载中必需至少有一个类型是类类型 ##4. 不要改变运算符的运算特性和优先级 比如把二元运算符改成一元就改变了运算特性 ##5. 只能重载成成员的运算符(不能是全局的运算符重载) * = (+= -= *= /= ...)等号运算符 * []下标取值运算符 * ()圆括号运算符 * ->(*)指针和指针解引用运算符 #只能重载成成员的运算符 ##1. []下标取值运算符 #includ <iostream> using namespace std; class Array { int index; int len; int* datas; public: Array(int len):len(len),index(0) { datas = new int[len]; } Array(const Array& a) { int* temp = a.datas; index = a.index; len = a.len; datas = new int[len]; for(int i = 0; i < len; i++) datas[i] = temp[i]; } ~Array() { delete[] datas; } static void expansion(Array& a) { int *temp = a.datas; a.len = 2*a.len + 1; a.datas = new int[a.len]; for(int i = 0; i < a.index; i++) a.datas[i] = temp[i]; delete[] temp; } void addData(int data) { if(index >= len) Array::expansion(*this); datas[index++] = data; } /* []下标取值运算符重载*/ int& operator[](unsigned int d) { return datas[d]; } /* ia = ib 系统默认提供的等号运算符会进行浅拷贝, 这样会造成内存泄露等一系列问题, 为了防止这种问题,我们要提供一个等号运算符重载*/ Array& operator=(const Array& a) { /* 如果不是自赋值*/ if(this != &a) { len = a.len; index = a.index; delete[] datas; datas = new int[len]; for(int i = 0; i < len; i++) datas[i] = a.datas[i]; } return *this; } friend ostream& operator<<(ostream& os, const Array& a) { os << "[ "; for(int i = 0; i <= index; i++) os << a.datas[i] << ' '; return os << ']'; } friend istream& operator>>(istream& is, Array& a) { cout << "请输入一个整数:" << endl; if(a.index >= a.len) Array::expansion(a); return is >> a.datas[a.index++]; } }; int main() { Array array(3); cin >> array >> array >> array >> array; array.addData(39); cout << array << endl; Array arr2(5); arr2 = array; cout << arr2 << endl; cout << array[4] << endl; array[2] = 32; cout << array[2] << endl; // 32 } ##2. ()运算符 * 可以做函数对象(可以像函数一样去使用对象) * 可以处理类型转换 能把当前对象类型转换成我们希望的类型 > operator 要转换成的类型 () { return 值;} ###2.1 例子代码 #include <iostream> using namespace std; class Product { int count; double price; public: Product(int count = 0, double orice) :count(count),price(price) { } /* 重载()运算符*/ double operator()(int c, double p) { return c*p; } double operator()(int c, double p, double pct) { return c*p*pct; } operator int() { return count; } operator double() { return price; } }; int main() { Product iphone; double sumprice = iphone(10, 4999.9); //49999 cout << sumprice << endl; cout << iphone(10,4999.9,0.8) << endl; // 399992 int c = (int)iphone; cout << c << endl; // 10 double d = (double)iphone; cout << d << endl; // 4999.9 } ###2.2 扩展 把某一个基本类型编程对象类型的方法`单参数构造机制` 如何防止单参构造的隐式转换??? 在类型的构造函数前加`explicit`关键值 ##3 ->和*运算符重载 把一个不是指针的类型可以当做指针类型的操作 ###3.1 智能指针 ####3.1.1 智能指针的原理 用一个栈对象管理堆对象. ####3.1.2 例子代码 #include <iostream> #include <memory> using namespace std; class A { public: A() { cout << "A()" << endl; } ~A() { cout << "~A()" << endl; } void show() { cout << "this is in A show()" << endl; } }; void foo() { A* pa = new A(); /* 这里尖括号是模板的知识点,暂不考虑*/ auto_ptr<A> myptr(pa); myptr->show(); } int main() { foo(); /*显示结果: A() this is in A show() ~A() */ } ###3.2 重载-> 和 * 达到和智能指针相同效果 #include <iostream> using namespace std; class A { public: A() { cout << "A()" << endl; } ~A() { cout << "~A()" << endl; } void show() { cout << "this is in A show()" << endl; } }; class myptr { A* data; public: myptr(A* data = NULL):data(data) { } ~myptr() { delete data; } A* operator->() { return data; } A& operator*() { return *data; } }; void foo() { A* pa = new A(); myptr ptr(pa); /* 编译器优化代码*/ myptr->show(); //myptr->->show(); (*myptr).show(); } int main() { foo(); /*输出结果: A() this is in A show() this is in A show() ~A() */ } ##4. new delete运算符重载(开发很少用) > void* operator new(size_t size); > void operator delete(void* ptr); > void* operator new[](size_t size); > void operator delete[](void* ptr); 例子代码 #include <iostream> #include <cstdlib> using namespace std; class A { int x; int y; public: A() { cout << "A()" << endl; } ~A() { cout << "~A()" << endl; } }; /* 以下两个特殊的函数重载 可以是全局函数,也可以是成员函数,也可以使静态成员函数,在语法和功能上没有任何区别*/ void* operator new(size_t size) { cout << "size = " << size << endl; return malloc(size); } void operator delete(void* ptr) { cout << "ptr = " << ptr << endl; free(ptr); } int main() { A* pa = new A(); delete pa; /*输出结果: size = 8 A() ~A() ptr = 0xc72030*/ }
上一篇:
09string/迭代器iterator/面向对象编程三大特征/继承
下一篇:
07成员指针/运算符重载/友元函数/输入输出运算符重载
0
赞
167 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
立即登录
, 发表评论.
没有帐号?
立即注册
0
条评论
More...
文档导航
没有帐号? 立即注册