1. 多个运算符连续,系统会按照一定的顺序逐个处理
Teacher t;
cout << ~t << endl;
2. 运算符重载的两种情况
不在类中完成
Teacher& operator ~ (const Teacher& t){
...
return t;
}
在类中完成
bool T::operator!(){
return (n==0);
}
3. 当指针成员指向动态内存时
指针成员指向动态内存,以下三个函数必须自己写
- 拷贝构造
- 等号复制
- 析构函数
4. = -> [] () 只能用成员函数重载
类中只有一个对象,且能访问:单例模式
内存释放:创建计数器的方式避免重复释放
#include <iostream>
#include <string>
using namespace std;
struct date{
int year;
int mouth;
int day;
};
struct Person{
string name;
int age;
bool gender;
double salary;
date birth;
Person(){cout << "创建Person对象 " << this << endl;}
~Person(){cout << "释放Person对象 " << this << endl;}
};
class autoptr{
public:
//注:这两个变量应该是私有的,只是为了演示方便
Person* p;
int cnt;
autoptr(Person* p):p(p),cnt(1){}
//这个类的->有一个隐含的问题,就是复制!
//因为复制时初始化另一个对象并没有为其开辟新的空间,只是指向被复制对象的内存地址
//因此在释放时候就会出现同一个内存被释放两边的问题
//因此引入了 cnt 计数器,只有第一次开辟该内存时才是可以被释放的
autoptr(const autoptr& a):p(a.p){cnt = a.cnt+1;}
~autoptr(){if(cnt==1)delete p;}
//这个运算符永远无参
//C++规定:希望通过该运算符访问谁的成员就返回谁的地址
Person* operator->(){
return p;
}
//返回它所指向对象本身,因此返回值是引用,不是复制一份
//C++规定:希望通过该运算符访问谁的成员就返回谁的对象
Person& operator*(){
return *p;
}
};
int main(){
// 等价于autoptr a(new Person);
// 这其实就是初始化了一个 Person 然后利用autoptr(Person* p);
// 这个构造函数赋值给a
autoptr a = new Person;
//等价于 (*a.p).age = 99;
//编译器处理:a.operator->()->name
a->age = 120;
cout << a->age << endl;
a->name = "abc";
cout << (*a).name << endl;
(*a).age = 11;
autoptr b = a;
cout << b.cnt << endl;
getchar();
return 0;
}
内存释放:开辟两个空间
#include <iostream>
#include <string>
using namespace std;
class Stack{
typedef unsigned int uint;
typedef string T;
T* men;
uint max;
uint len;
public:
Stack(uint n): men(new T[n]),max(n),len(0) {}
//开辟两个空间避免重复释放
Stack(const Stack& s): men(new T[s.max]), max(s.max),len(s.len) {}
uint max_size()const{
return max;}
uint size()const{
return len;}
Stack& push(const T& e){
if (len>=max)
throw 0;
men[len++] = e;
return *this;}
T pop(){
if(len==0)
throw 1;
return men[--len];}
void print()const{
for(uint i=0; i<len; i++){
cout << men[i] << " ";}
cout << endl;}
~Stack(){
delete[] men;};
Stack& operator=(const Stack& s2){
//这是避免自己给自己赋值的情况
if(this == &s2){
return *this;}
this->len = s2.len;
this->max = s2.len;
delete [] men;
this->men = new(T [this->max]);
for (uint i=0; i<len; i++){
men[i] = s2.men[i];
}
return *this;
}
};
int main(){
Stack s1(5);
Stack s2(s1);
//这个写法在调用时会复制一份,但在释放时就会重复释放
//s1.operator(s2)
s1 = s2;
getchar();
return 0;
}
前后 ++ -- 、double 等运算符重载
#include <iostream>
#include <string>
using namespace std;
class F{
int n;
int d;
public:
F(int n=0, int d=1):n(n),d(d){}
friend ostream& operator << (ostream& o, const F& f){
o << f.n << " / " << f.d ;
return o;
}
F& operator ++ (){
n += d;
return *this;
}
F operator ++ (int){//为了区分前后++,引入哑元
F old(*this);
n += d;
return old;
}
friend F& operator -- (F& f){
f.n -= f.d;
return f;
}
friend F operator -- (F& f, int){
F old(f);
f.n -= f.d;
return old;
}
//类型转换运算符函数的转换返回类型省略
//因为返回值类型总是和重载的类型函数相同
operator double (){
return 1.0*n/d;
}
operator bool (){
return n;
}
}
int main(){
F f1(2,5), f2(4,9), f3(17,3);
++f1; //f1.operator++();
f2++; //f2.operator++(0); //为了区分前后++,引入哑元
--f1; //f1.operator--();
f2--; //f2.operator--(0);
double(f1);
getchar();
return 0;
}
实参初始化形参
class F{
int n;
F(int n):n(n){};
}
void func(F f){}
int mian(){
func(6);
return 0;
}
//上面的写法是对的,其实是中间省略了一步
// func前后 ++ -- 、double ()等运算符重载
重载[] ()
#include <iostream>
#include <string>
using namespace std;
class A{
public:
typedef unsigned int uint;
private:
int* p;
uint n;
public:
A(uint n):n(n){
p = new int[n];
if (NULL == p){
throw 0;
memset(p, 0, n*4);
}
}
~A(){
delete[] p;
}
uint size()const{
return n;
}
int& operator[] (uint i)const{
//越界检查
if (i >= n){
throw 1;
}
//这个地方不会有递归
//因为调用函数是A类型
//返回函数是 int* 类型的
return p[i];
}
int& operator[] (const char* c)const{
int i = atoi(c);
if (i <0 || i >= n){
throw 1;
}
return p[i];
}
void operator() (int v){
for (uint i=0; i<n; i++){
p[i] += v;
}
}
void operator() (const char* s){
int v = atoi(s);
for (uint i=0; i<n; i++){
p[i] += v;
}
}
};
ostream& operator<< ( ostream& o, const A& a ){
o << "{ ";
for (int i=0; i<a.size(); i++){
cout << a[i] << ' ';
}
o << "}";
return o;
}
int main(){
A x(5), y(8);
x[2] = 20; //x.operator[](2);
y["6"] = 66; //y.operator[](6);
x(3); //x.operator()(3);
y("5"); //y.operator()(5);
getchar();
return 0;
}