目录
(1)什么是运算符重载
(2)运算符重载的本质是函数调用
(3)可以与不可以重载的运算符
(4)单目运算符与双目符重载区别
(5)双目运算符重载举例
重载=操作符
用友元函数实现重载<<操作符
重载下标运算符[]
重载函数调用符()
(6)单目运算符重载举例
重载右值++运算符
用双目运算符的思想重载左值++运算符
重载箭头->运算符
(7)运算符重载步骤总结
(8)为什么不建议重载&&和||操作符
(9)运算符重载在项目开发中的应用
自定义字符串类
自定义智能指针类
(1)什么是运算符重载
⽤复数类举例
Complex c3 = c1 + c2;
原因 Complex是⽤户⾃定义类型,编译器根本不知道如何进⾏加减。
编译器给提供了⼀种机制,让⽤户⾃⼰去完成,⾃定义类型的加减操作等。
这个机制就是运算符重载机制。
(2)运算符重载的本质是函数调用
全局函数角度:c1 + c2 从全局函数角度等价于函数调用:operator+(c1, c2)。
声明:Complex operator+(Complex &c1, Complex &c2) // 需要定义的全局函数
注意:运算符重载函数要操作私有成员时,需要在类中声明为友元函数。
使用:
- Complex c4 = operator+(c1, c2); // 正常像函数那样使用,函数名是"operator+"
- Complex c4 = c1 + c2; // 用符号使用
类成员函数角度:c1 - c2 从类成员函数角度 等价于函数调用:c1.operator-(c2)。
声明:Complex operator-(Complex &c2) // 需要定义类成员函数
因为c1-c2等价于c1.operator-(c2),要想能使用c1-c2
就需要在c类的内部自定义Complex operator-(Complex &c_object)函数
再以重载=为例,A类,通过类成员函数重载:a1=a2,等价于a1.operator=(a2),所以需要在A类的内部自定义A operator=(Complex &A_object)函数。
示例代码
#include <iostream>
class Complex
{
public:
int a;
int b;
public:
Complex(int a, int b)
{
this->a = a;
this->b = b;
}
void printCom()
{
std::cout << a << "+" << b << "i" << std::endl;
}
public:
// 类成员函数实现运算符重载
Complex operator*(Complex &c2)
{
Complex temp(this->a * c2.a - this->b * c2.b,
this->a * c2.b + this->b * c2.a);
return temp;
}
};
// 全局函数实现特定对象之间的运算
Complex com_add(Complex &c1, Complex &c2)
{
Complex temp(c1.a + c2.a, c1.b + c2.b);
return temp;
}
// 全局函数实现运算符重载
Complex operator+(Complex &c1, Complex &c2)
{
Complex temp(c1.a + c2.a, c1.b + c2.b);
return temp;
}
int main()
{
Complex c1(1, 2), c2(3, 4);
// a + bi 复数运算规则
// 类也是一种数据类型
// 用户自定义数据类型 两个对象之间运算 C++编译器 是不知道如何进行运算
// 1.定义全局函数进行计算
Complex c3 = com_add(c1, c2);
c3.printCom(); //4+6i
// 2.运算符重载
// c++编译器应该给我们程序员提供一种机制
// 让自定义数据类型 有机会 进行 运算符操作 ====> 运算符重载机制
// 全局函数实现
Complex c4 = operator+(c1, c2);
c4.printCom(); // 4+6i
Complex c5 = c1 + c2;
c5.printCom(); // 4+6i
// 类成员函数实现
Complex c6 = c1 * c2;
c6.printCom(); //-5+10i
return 0;
}
(3)可以与不可以重载的运算符
可以重载的运算符:
+ | - | * | / | % | ^ | & | | | ~ |
! | = | < | > | += | -= | *= | /= | % |
^= | &= | |= | << | >> | >>= | <<= | == | != |
<= | >= | && | || | ++ | -- | ->* | -> | [ ] |
() | new | delete | new[] | delet[] |
不能重载的运算符
. | :: | .* | ?: | sizeof |
(4)单目运算符与双目符重载区别
单目运算符:比如++,像a++,++b等。
双目运算符:比如+, =, ==,像a+b,c=d,c==d等。
运算符重载函数:[返回值] operator[运算符] (参数...) { ... };
对于参数:重载函数的参数个数必须与运算符原来的个数一致。比如+号的参数就是左加数和右加数两个。那么当我们重载加号时也要保证有左右两个加数作为参数。
对于双目运算符:
-
用全局函数重载时,左边形参作为运算符左操作数,右边形参是右操作数。
-
用类成员函数重载时,只需要写一个参数即可,因为类的成员函数默认有一个this指针,有一个参数就已经被this指针包含了,this指向运算符左参数。以减号为例,两个时间类a和b相减时。如果是a - b,那么this指针指向a,反之则指向b。在声明函数时,我们只需要写右参数即可。a - b的话只需要写 int operator-(Time b);
对于单目运算符:
运算符在左侧,参数在右侧,比如++a(说明:a++这种比较特殊,运算符是在右侧,这种用用特殊技巧重载)
- 用全局函数重载时,右操作数是形参。
- 用类成员函数重载时,单目运算符由于只有一个参数,且该参数被this所指向,那么我们无需声明任何参数即可。this所指向运算符右参数。
对于返回值:运算符的返回值类型取决于该重载函数的作用是什么。
- 比如a + b的作用是得到一个加数,那么返回值就是a+b的值。a += b的作用是让a的值改变,既然是让参数a的值改变,那么就无需返回值。
- 还有就是如果我们需要运算符支持多次操作那么也需要返回值。比如流插入运算符<<。我们可能需要多次进行插入,像cout << a << b << c;之类就需要返回流ostream本身以便于之后的流插入工作。
(5)双目运算符重载举例
重载=操作符
示例代码
#include <iostream>
#include <stdlib.h>
#include <cstring>
class Name
{
public:
Name(const char *p, int index)
{
m_len = strlen(p);
m_p = (char *)malloc(m_len + 1);
strcpy(m_p, p);
this->index = index;
}
Name(const Name &name)
{
std::cout << "copy generate func" << std::endl;
m_len = name.m_len;
m_p = (char *)malloc(m_len + 1);
strcpy(m_p, name.m_p);
this->index = 0;
}
/*
重载=运算符
首选因为obj3 = obj1; 所以obj3.operator=(obj1)
再因为有链式编程 obj1 = obj2 = obj3的需要,所以需要返回引用
*/
Name &operator=(Name &name)
{
std::cout << "operator= func" << std::endl;
if (this->m_p != NULL)
{
free(m_p);
m_p = NULL;
m_len = 0;
}
this->m_len = name.m_len;
this->m_p = (char *)malloc(m_len + 1);;
strcpy(m_p, name.m_p);
// 返回左操作参数的引用
std::cout << getIndex() << std::endl;
return *this;
}
~Name()
{
if (m_p != NULL)
{
free(m_p);
m_p = NULL;
m_len = 0;
}
}
public:
void printInfo()
{
std::cout << "&(*this)=" << this
<< ", name=" << this->m_p
<< ", index=" << this->index
<< std::endl;
// &(*this) = this的值
}
void setIndex(int index){this->index=index;}
int getIndex(){return index;}
protected:
private:
char *m_p;
int m_len;
int index;
};
void objplaymain()
{
std::cout << "-------------A--------------" << std::endl;
Name obj1("hello world", 1);
Name obj2 = obj1; // 调用拷贝构造函数
obj2.setIndex(2);
obj2.printInfo();
std::cout << "-------------B--------------" << std::endl;
Name obj3("obj3", 3);
obj3 = obj1; // 调用运算符重载函数
// obj3.operator=(obj1)
obj3.printInfo();
std::cout << "-------------C--------------" << std::endl;
Name obj4("obj4", 4);
obj1 = obj4 = obj3; // 调用运算符重载函数
//思考obj1 = obj4 = obj3;的运行过程!
//从右到左,先obj4 = obj3,同时根据类中=重载定义,返回的是obj4
//然后obj1 = obj4,返回obj1
}
int main()
{
objplaymain();
return 0;
}
运行结果
-------------A--------------
copy generate func
&(*this)=0x7ffd72212180, name=hello world, index=2
-------------B--------------
operator= func
3
&(*this)=0x7ffd72212170, name=hello world, index=3
-------------C--------------
operator= func
4
operator= func
1
用友元函数实现重载<<操作符
当⽆法修改左操作数的类时,使⽤友元函数进⾏重载
istream 和 ostream 是 C++ 的预定义流类,cin 是 istream 的对象,cout 是 ostream 的对象。
运算符 << 由ostream 重载为插⼊操作,⽤于输出基本类型数据。
运算符 >> 由 istream 重载为提取操作,⽤于输⼊基本类型数据。
⽤友员函数重载 > ,输出和输⼊⽤户⾃定义的数据类型。
由于编译器ostream源码我们是拿不到的,所以不能通过设置成员函数来重载<<运算符,这里可以通过友元函数实现。
示例代码
#include <iostream>
class Complex
{
private:
int a;
int b;
public:
// friend void operator<<(std::ostream &os_obj, Complex &c1);
friend std::ostream &operator<<(std::ostream &os_obj, Complex &c1);
public:
Complex(int a, int b)
{
this->a = a;
this->b = b;
}
void printCom()
{
std::cout << a << "+" << b << "i" << std::endl;
}
};
/*
void operator<<(std::ostream &std::cout, Complex &c1)
{
std::cout << c1.a << "+" << c1.b << "i" << std::endl;
}
*/
std::ostream &operator<<(std::ostream &os_obj, Complex &c1)
{
os_obj << c1.a << "+" << c1.b << "i ";
return os_obj;
}
int main()
{
// 1.编译器按照已有数据类型输出
int a = 10;
std::cout << a << std::endl;
// 2.对于自定义数据类型,需重载运算符输出
// 这里用友元函数重载了<<运算符
// 使得既能输出基础数据类型,也能输出自定义类型,也能支持链式编程
Complex c1(1, 2);
Complex c2(3, 4);
std::cout << c1;
std::cout << std::endl;
std::cout << c1 << "hello world" << std::endl;
std::cout << c1 << c2 << "xxxxxxx" << std::endl;
return 0;
}
运行结果
10
1+2i
1+2i hello world
1+2i 3+4i xxxxxxx
重载下标运算符[]
设 x 是类 X 的一个对象,则表达式x [ y ] 可被解释为 x . operator [ ] ( y )
示例代码
#include <iostream>
class Data
{
public:
Data(int value = 0)
{
this->value = value;
}
public:
int value;
};
class Test
{
public:
Test(int a = 0, int b = 0)
{
this->a = a;
this->b = b;
}
public:
// 重载[],使得能传递整数类型
int operator[](int index)
{
return a * index;
}
// 重载[],使得能传递Test类型
int operator[](const Test &t)
{
return b * t.a;
}
// 重载[],使得能传递Data类型,且能链式编程
Test &operator[](const Data &d)
{
std::cout << d.value << "\t";
return *this;
}
private:
int a;
int b;
};
int main()
{
Test test(1, 2);
// []传递整型
std::cout << test[3] << std::endl;
// []传递Test类型
Test test2(3, 4);
std::cout << test[test2] << std::endl;
// []传递Data类型
Data data1(3), data2(18), data3(99);
test[data1][data2][data3];
return 0;
}
运行结果
3
6
3 18 99
重载函数调用符()
设 x 是类 X 的一个对象,则表达式x ( arg1, arg2, … )可被解释为x . operator () (arg1, arg2, … )
#include <iostream>
#include <string>
// 类的声明
class F
{
public:
double operator()(double x, double y);
std::string operator()(std::string x, std::string y);
};
// 类的具体实现
double F::operator()(double x, double y)
{
return x * x + y * y;
}
std::string F::operator()(std::string x, std::string y)
{
std::string ret = "(";
if (x.size() == 0)
ret += " ";
else
ret += x[0];
if (y.size() == 0)
ret += " ";
else
ret += y[0];
ret += ")";
return ret;
}
int main()
{
F f;
std::cout << f(5.2, 2.5) << std::endl;; // 33.29
std::cout << f.operator()(5.2, 2.5) << std::endl;; // 33.29
std::cout << f("hello", "world") << std::endl;; // (hw)
std::cout << f("", "xxxxx") << std::endl;; // ( x)
return 0;
}
(6)单目运算符重载举例
重载右值++运算符
右值++运算符,++b,可被解释为operator ++ ( b )
示例代码
#include <iostream>
using namespace std;
class Complex
{
private:
int a;
int b;
public:
Complex(int a, int b)
{
this->a = a;
this->b = b;
}
void print_value()
{
cout << a << "+" << b << "i" << endl;
}
public:
// 右值++重载用成员函数实现
Complex &operator++()
{
std::cout << "internal reload" << std::endl;
this->a++;
this->b++;
return *this;
}
// 右值--重载用全局函数实现
friend Complex &operator--(Complex &c);
};
Complex &operator--(Complex &c)
{
std::cout << "external reload" << std::endl;
c.a--;
c.b--;
return c;
}
int main()
{
Complex c1(1, 2);
Complex temp = ++c1; // internal reload
c1.print_value(); // 2+3i
temp.print_value(); // 2+3i
--c1; // external reload
c1.print_value(); // 1+2i
return 0;
}
运行结果
internal reload
2+3i
2+3i
external reload
1+2i
用双目运算符的思想重载左值++运算符
++作为单目运算符,直接重载的话,实现的是右值++,要重载左值++,技巧在于用一个占位符作为运算符重载函数的第二个参数,这样原本的变量就变成了左操作数。
示例代码
#include <iostream>
class Complex
{
private:
int a;
int b;
// 重载右值++
friend Complex &operator++(Complex &c1);
// 重载左值++
friend Complex operator++(Complex &c1, int);
public:
Complex(int a = 0, int b = 0)
{
this->a = a;
this->b = b;
}
void printCom()
{
std::cout << a << "+" << b << "i" << std::endl;
}
public:
// 重载右值--
Complex &operator--()
{
this->a--;
this->b--;
return *this;
}
// 用占位符实现重载左值++
Complex operator--(int)
{
Complex temp = *this;
this->a -= 10;
this->b -= 10;
return temp;
}
};
// 重载右值++
Complex &operator++(Complex &c1)
{
c1.a++;
c1.b++;
return c1;
}
// 重载左值++
// 用占位符区分右值++和左值++
// 这里添加一个占位符,实现左值++重载
Complex operator++(Complex &c1, int)
{
Complex temp = c1;
c1.a += 10;
c1.b += 10;
return temp;
}
int main()
{
Complex c1(1, 2);
// 为了区分左值++和右值++正确被重载
// 右值++的变化量为1,左值++的变化量为10
// 重载左值++操作符
Complex temp = c1++;
//Complex temp = operator++(c1, 3);
c1.printCom(); // 11+12i
temp.printCom(); // 1+2i
// 重载右值++操作符
temp = ++c1;
//temp = operator++(c1);
c1.printCom(); // 12+13i
temp.printCom(); // 12+13i
// 重载左值--操作符
temp = c1--;
c1.printCom(); // 2+3i
temp.printCom(); // 12+13i
// 重载右值--操作符
temp = --c1;
c1.printCom(); // 1+2i
temp.printCom(); // 1+2i
return 0;
}
重载箭头->运算符
->一般用在指针当中。对它的重载稍微特殊一点,设 x 是类 X 的一个对象,则对于表达式x -> y :
- 需要先看x ->部分,对应运算符重载函数x. operator ->(),如果该函数返回指针,比如返回p,则x ->就相当于返回p->,然后x -> y就相当于p->y,就是指针访问成员y,这里y可以是成员变量,比如p->a,也可以是成员函数,比如p->action()。
- 如果函数x. operator ->()返回的不是指针,而是一个对象(比如m,假设m是类M的一个对象),则继续对该对象调用其重载了的箭头运算符(意味着类M也必须要对->进行重载,否则会报错),直到返回的是一个指针,假设为p,则最后就是在调用p->y。
示例代码
#include <iostream>
class firstClass
{
public:
firstClass* operator->()
{
std::cout << "firstClass ->() is called!" << std::endl;
return this;
}
void action()
{
std::cout << "firstClass action() is called!" << std::endl;
return;
}
};
class myClass
{
firstClass firstObj;
public:
firstClass& operator->()
{
std::cout << "myClass ->() is called!" << std::endl;
return firstObj;
}
void action()
{
std::cout << "myClass action() is called!" << std::endl;
return;
}
};
int main()
{
myClass obj;
obj->action();
return 0;
}
运行结果
myClass ->() is called!
firstClass ->() is called!
firstClass action() is called!
(7)运算符重载步骤总结
运算符重载步骤
1)要承认操作符重载是一个函数,写出函数名称。
2)根据操作数,写出函数参数。
3)根据业务,完善函数返回值(看函数是返回引用 还是指针 还是元素),及实现函数业务。
4)根据情况考虑用全局函数还是类成员函数方法实现。
(8)为什么不建议重载&&和||操作符
&&和||是C++中非常特殊的操作符,&&和||内置实现了短路规则。
操作符重载是靠函数重载来完成的,操作数作为函数参数传递,C++的函数参数都会被求值,无法实现短路规则。
以下示例代码演示了可以实现&&的运算符的重载,但无法实现短路规则。
#include <iostream>
class Test
{
private:
int i;
public:
Test(int i = 0)
{
this->i = i;
}
public:
Test operator+(const Test &obj)
{
Test ret(0);
std::cout << "+ reload func" << std::endl;
ret.i = i + obj.i;
return ret;
}
bool operator&&(const Test &obj)
{
std::cout << "&& reload func" << std::endl;
return i && obj.i;
}
};
int main()
{
// 1.查看&&的短路规则
int a1 = 0;
int a2 = 1;
// 注意:&&操作符的结合顺序是从左向右
if (a1 && a2++) //有一个是假,则不在执行下一个表达式的计算
{
/* */
}
std::cout << a2 << std::endl; // 1
// 2.重载&&后无法实现短路规则
Test t1 = 0;
Test t2 = 1;
// if( t1 && (t1 + t2) )
// t1 && t1.operator+(t2)
// t1.operator&&( t1.operator+(t2) )
// && || 重载他们 不会产生短路效果
if (t1 && (t1 + t2)) { ; }
// t1.operator+(t2) && t1;
//(t1.operator+(t2)).operator&&(t1);
// 两个函数都被执行了,而且是先执行了+
// 说明没有实现短路规则
return 0;
}
运行结果
1
+ reload func
&& reload func
(9)运算符重载在项目开发中的应用
自定义字符串类
用来练习各种运算符重载
构造函数要求
MyString a;
MyString a(“dddd”);
MyString b = a;
常用的操作符
> != == > < =
MyString.h
#include <iostream>
using namespace std;
//C中没有字符串,因此需要建一个字符串类
//C++中 我们来设计一个字符串 以零结尾的字符串
//空串 ""
class MyString
{
public:
//用友元函数重载输入输出流
friend ostream &operator<<(ostream &cout, MyString &s);
friend istream &operator>>(istream &cin, MyString &s);
public:
//构造函数和析构函数
MyString(int len = 0); //传入整数构造
MyString(const char *p); //传入字符串构造
MyString(const MyString &s); //传入字符串类对象构造
~MyString();
public:
//重载等号操作符 =
MyString& operator=(const char *p);
MyString& operator=(const MyString &s);
//重载下标操作符 []
public:
char& operator[](int index);
//重载 == != 操作符
public:
bool operator==(const char *p) const;
bool operator==(const MyString &s) const;
bool operator!=(const char *p) const;
bool operator!=(const MyString &s) const;
//重载 大于小于操作符
public:
int operator<(const char *p) const;
int operator>(const char *p) const;
int operator<(const MyString &s) const;
int operator>(const MyString &s) const;
public:
//字符串类技巧:把指针露出来
char *c_str()
{
return m_p;
}
const char*c_str2()
{
return m_p;
}
int getlen()
{
return m_len;
}
private:
int m_len;
char *m_p;
};
MyString.cpp
#include <iostream>
using namespace std;
#include "MyString.h"
#include <cstring>
ostream &operator<<(ostream &cout, MyString &s)
{
cout << s.m_p;
return cout;
}
istream &operator>>(istream &cin, MyString &s)
{
cin >> s.m_p;
return cin;
}
// MyString::MyString(int len = 0)
// 会error,‘MyString::MyString(int)’的第 1 个形参指定了默认实参
MyString::MyString(int len)
{
if (len == 0)
{
m_len = len;
m_p = new char[m_len + 1];
strcpy(m_p, "");
}
else
{
m_len = len;
m_p = new char[m_len + 1];
memset(m_p, 0, m_len);
}
}
MyString::MyString(const char *p)
{
if (p == NULL)
{
m_len = 0;
m_p = new char[m_len + 1];
strcpy(m_p, "");
}
else
{
m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p, p);
}
}
//拷贝构造函数
// MyString s3 = s2;
MyString::MyString(const MyString &s)
{
m_len = s.m_len;
m_p = new char[m_len + 1];
strcpy(m_p, s.m_p);
}
MyString::~MyString()
{
if (m_p != NULL)
{
delete[] m_p;
m_len = 0;
m_p = NULL;
}
}
// S4 = "hello world";
MyString &MyString::operator=(const char *p)
{
// 1.先释放旧内存
if (m_p != NULL)
{
delete[] m_p;
m_len = 0;
}
// 2.根据p分配内存
if (p == NULL)
{
m_len = 0;
m_p = new char[m_len + 1];
strcpy(m_p, "");
}
else
{
m_len = strlen(p);
m_p = new char[m_len + 1];
strcpy(m_p, p);
}
return *this;
}
// s4 = s2;
MyString &MyString::operator=(const MyString &s)
{
// 1 旧内存释放掉
if (m_p != NULL)
{
delete[] m_p;
m_len = 0;
}
// 2 根据s分配内存
m_len = s.m_len;
m_p = new char[m_len + 1];
strcpy(m_p, s.m_p);
return *this;
}
char &MyString::operator[](int index)
{
return m_p[index];
}
// (s2 == "hello world")
bool MyString::operator==(const char *p) const
{
if (p == NULL)
{
if (m_len == 0)
{
return true;
}
else
{
return false;
}
}
else
{
if (m_len == strlen(p))
{
return !strcmp(m_p, p);
}
else
{
return false;
}
}
}
bool MyString::operator!=(const char *p) const
{
return !(*this == p);
}
bool MyString::operator==(const MyString &s) const
{
if (m_len != s.m_len)
{
return false;
}
return !strcmp(m_p, s.m_p);
}
bool MyString::operator!=(const MyString &s) const
{
return !(*this == s);
}
// (s3 < "bbbb")
int MyString::operator<(const char *p) const
{
return strcmp(this->m_p, p);
}
int MyString::operator>(const char *p) const
{
return strcmp(p, this->m_p);
}
int MyString::operator<(const MyString &s) const
{
return strcmp(this->m_p, s.m_p);
}
int MyString::operator>(const MyString &s) const
{
return strcmp(s.m_p, m_p);
}
test.cpp
#include <iostream>
using namespace std;
#include <cstring>
#include "MyString.h"
int main01()
{
MyString s1(1);
MyString s2("s2");
// MyString s2_2 = NULL; //这句会报错
MyString s2_2 = "hello world";
MyString s3 = s2;
MyString s4 = "s4444444444";
//测试运算符重载 = [] <<
s4 = s2;
cout << s4 << endl; // "s2"
s4 = "s2222";
s4[1] = '4';
cout << s4 << endl; // "s4222"
return 0;
}
int main02()
{
MyString s1;
MyString s2("s2");
MyString s3 = s2;
if (s2 == "aa")
printf("equal\n");
else
printf("no equal\n");
if (s3 == s2)
printf("equal\n");
else
printf("no equal\n");
return 0;
}
int main03()
{
MyString s1;
MyString s2("s2");
MyString s3 = s2;
s3 = "aaaa";
int tag = (s3 < "bbb");
if (tag < 0)
printf("s3 less than bbb\n");
else
printf("s3 more than bbb\n");
MyString s4 = "aaaaffff";
strcpy(s4.c_str(), "aa111");
cout << s4 << endl;
return 0;
}
int main04()
{
MyString s1(128);
cout << "\n input content(Enter finish):"; // hello world
cin >> s1;
cout << s1; // hello
//目前没有正确处理空格
//可以完善
return 0;
}
int main()
{
// main01();
// main02();
// main03();
main04();
return 0;
}
自定义智能指针类
1问题抛出:指针使用过程中,经常会出现内存泄漏和内存多次被释放。
2 解决方案:例如:boost库的智能指针。项目开发中,要求开发者使用预先编写的智能指针类对象代替C语言中的原生指针。
3 智能指针思想
- 工程中的智能指针是一个类模板
- 通过构造函数接管申请的内存
- 通过析构函数确保堆内存被及时释放
- 通过重载指针运算符* 和 -> 来模拟指针的行为
- 通过重载比较运算符 == 和 != 来模拟指针的比较
示例代码
#include <iostream>
using namespace std;
class Test
{
public:
Test()
{
this->a = 10;
}
void printT()
{
cout << a << endl;
}
private:
int a;
};
class MyTestPointer
{
public:
public:
MyTestPointer()
{
p = NULL;
}
MyTestPointer(Test *p)
{
this->p = p;
}
~MyTestPointer()
{
delete p;
}
Test *operator->()
{
return p;
}
Test &operator*()
{
return *p;
}
protected:
Test *p;
};
class MyIntPointer
{
public:
public:
MyIntPointer()
{
p = NULL;
}
MyIntPointer(int *p)
{
this->p = p;
}
~MyIntPointer()
{
delete p;
}
int *operator->()
{
return p;
}
int &operator*()
{
return *p;
}
protected:
int *p;
};
void test1()
{
Test *p = new Test;
p->printT();
delete p;
MyTestPointer myp = new Test; //构造函数
myp->printT(); //重载操作符 ->
};
void test2()
{
int *p = new int(100);
cout << *p << endl;
delete p;
MyIntPointer myp = new int(200);
cout << *myp << endl; //重载*操作符
};
int main()
{
test1();
test2();
return 0;
}
end