一个简单的类
class test
{
private:
int m_a,m_b;
int *p;//存储m_a的地址
};
1.算数运算符重载
加号运算符的重载 (其他运算符同理)
1.1 全局函数重载
class test
{
private:
int m_a, m_b;
public:
test(int a = 0, int b = 0) : m_a(a), m_b(b) {}
friend test operator+(const test &a, const test &b);
//类外无法访问到类内的私有成员 需要将该函数添加为友元
void display()
{
cout << "m_a:" << m_a << endl;
cout << "m_b:" << m_b << endl;
}
};
test operator+(const test &a, const test &b)
{
test tmp;
tmp.m_a = a.m_a + b.m_a;
tmp.m_b = a.m_b + b.m_b;
return tmp;
}
1.2 成员函数重载
class test
{
private:
int m_a, m_b;
public:
test(int a = 0, int b = 0) : m_a(a), m_b(b) {}
test operator+(const test &b)//此时本对象相当于全局函数中的参数a
{
test tmp;
tmp.m_a = m_a + b.m_a;
tmp.m_b = m_b + b.m_b;
return tmp;
}
void display()
{
cout << "m_a:" << m_a << endl;
cout << "m_b:" << m_b << endl;
}
};
2.左移运算符重载
例:将下面代码中的display改为用cout进行输出
class test
{
private:
int m_a, m_b;
public:
test(int a = 0, int b = 0) : m_a(a), m_b(b) {}
void display()
{
cout << "m_a:" << m_a << endl;
cout << "m_b:" << m_b << endl;
}
};
//注意:左移运算符不应在类内重载 (类内重载格式为 tmp<<cout; 不符合书写规范)
//注意添加友元
ostream &operator<<(ostream &os, const test &t)
{
os << "m_a:" << t.m_a << endl;
os << "m_b:" << t.m_b << endl;
return os;
}
对于上面的代码 cout为ostream类型且只能存在一个 所以需要用引用
返回值要以引用方式返回 保证可以进行链式操作
3.自增运算符重载
class test
{
private:
int m_a, m_b;
public:
friend test operator+(const test &a, const test &b);
friend ostream &operator<<(ostream &os, const test &t);
test(int a = 0, int b = 0) : m_a(a), m_b(b) {}
//返回一个引用 便于处理++(++t)等情况
test &operator++()//前置++
{
m_a++,m_b++;
return *this;
}
test &operator++(int)//后置++
{
//先存储初始值 自增后再返回初值
test tmp = *this;
m_a++,m_b++;
return tmp;
}
};
C++通过占位参数 (类型必须为int) 来区分前置和后置自增
(理论上++i的效率比i++更高)
4.赋值运算符重载
C++默认实现了赋值操作(浅拷贝)
当类内存在指针时 为了避免重复释放 需要重载赋值运算符(使用深拷贝)
4.1 错误代码
class test
{
private:
int m_a, m_b;
int *p;
public:
test(int a = 0, int b = 0) : m_a(a), m_b(b), p(new int(m_a)) {}
~test()
{
if (p != NULL)
{
delete p;
p = NULL;
}
}
};
int f()
{
test a(1, 2), b;
b = a;
//此时a b中的指针指向同一块内存区域
//当释放掉一个后 再次释放就会出错(第二个类内p仍然不为NULL)
}
4.2 解决方法
对赋值运算符进行重载 为第二个类的指针开辟一块新空间
class test
{
private:
int m_a, m_b;
int *p;
public:
test(int a = 0, int b = 0) : m_a(a), m_b(b), p(new int(m_a)) {}
~test()
{
if (p != NULL)
{
delete p;
p = NULL;
}
}
test &operator=(const test &t)
{
m_a = t.m_a;
m_b = t.m_b;
p = new int(t.m_a);
return *this;
}
};
返回引用可以实现 a=b=c; 的操作
赋值运算符不能重载为全局函数
5.关系运算符重载
具体根据代码需要进行重载
class test
{
private:
int m_a, m_b;
public:
test(int a = 0, int b = 0) : m_a(a), m_b(b) {}
bool operator==(const test &t)
{
return (m_a == t.m_a && m_b == t.m_b);
}
bool operator!=(const test &t)
{
return (m_a != t.m_a && m_b != t.m_b);
}
bool operator>(const test &t)
{
return (m_a + m_b > t.m_a + t.m_b);
}
};
6.函数调用运算符重载
仿函数(没有固定写法)
class test
{
private:
int m_a, m_b;
public:
test(int a = 0, int b = 0) : m_a(a), m_b(b) {}
void operator()(int a, int b)
{
m_a = a;
m_b = b;
}
void operator()()
{
cout << "m_a = " << m_a << endl;
cout << "m_b = " << m_b << endl;
}
};
//调用
int main()
{
test t;
t(10, 20);
t();
return 0;
}