一、类型转换运算符重载
一般基本数据类型可以通过转换构造函数转换成类类型,但是类类型不能直接转换为基本数据类型。这些是数据类型转换的一般原则:简单类型一般可以转换成复杂数据类型,但是复杂数据类型一般不能直接转换为基本数据类型。这个时候就需要我们重载类型转换运算符。类型转换运算符可以实现从 类类型->自定义数据类型 的转换。和构造函数 自定义数据类型->类类型 的转换方向正好相反。
我们改进Integer的实现,增加转换运算符的重载:
#include <iostream>
using namespace std;
class Integer
{
public:
Integer(int n);
~Integer();
Integer& operator++();
Integer operator++(int n);
operator int();
void Display() const;
private:
int n_;
};
Integer::Integer(int n) : n_(n)
{
cout<<"construct:"<<endl;
}
Integer::~Integer()
{
}
Integer& Integer::operator ++()
{
++n_;
return *this;
}
Integer Integer::operator++(int n)
{
Integer tmp(n_);
n_++;
return tmp;
}
Integer::operator int()
{
cout<<"类型转换运算符调用"<<endl;
return n_;
}
void Integer::Display() const
{
cout<<n_<<endl;
}
int add(int a, int b)
{
return a + b;
}
int main(void)
{
Integer n(100);
//调用转换构造函数,先调用转换构造函数,在调用=运算符
n = 200;
n.Display();
//n不能从Integer类类型直接转换为int,需要我们重载类型转换运算符
int sum = add(n, 100); //调用类型转换运算符
cout<<sum<<endl;
int x = n; //调用类型转换运算符
int y = static_cast<int>(n); //调用类型转换运算符
return 0;
}
打印结果:
construct:
construct:
200
类型转换运算符调用
300
类型转换运算符调用
类型转换运算符调用
二、->运算符重载
下面实现一个数据库操作的例子,重载->运算符实现转发:
#include <iostream>
using namespace std;
class DBHelper
{
public:
DBHelper() :isopen(false)
{
cout<<"DB ..."<<endl;
}
~DBHelper()
{
cout<<"~DB ..."<<endl;
}
void Open()
{
if (isopen) cout<<" Aleady Open ..."<<endl;
else cout<<"Open ..."<<endl;
isopen = true;
}
void Close()
{
if (isopen) cout<<"Close ..."<<endl;
else cout<<"Aleady Close ..."<<endl;
isopen = false;
}
void Query()
{
if (isopen) cout<<"Query ..."<<endl;
else cout<<"Please Open DB ..."<<endl;
}
private:
bool isopen;
};
class DB
{
public:
DB() { db_ = new DBHelper; } //利用确定性析构原理,类似于智能指针
~DB(){ delete db_; }
//重载指针运算符->
DBHelper* operator->(){ return db_; }
private:
DBHelper* db_;
};
int main()
{
DB db;
db->Open();
db->Close();
db->Open();
db->Query();
db->Close();
return 0;
}
三、operator new、operator delete的重载
首先我们先熟悉一下new的三种用法:
1、operator new 只分配内存。如char *p = new char[100];
2、new operator = operator new(分配内存) + 构造函数的调用 如Test *p = new Test(100);
3、placement new 只调用构造函数,不分配内存。所以内存必须是已经分配好的,placement只是把创建的对象放在已经分配好的内存空间里(可以是栈空间或者堆空间)。且析构函数不会自动调用,必须显式调用。
下面是new用法及new,delete重载例子:
#include <iostream>
using namespace std;
class Test
{
public:
Test(int n) : n_(n) { cout<<"Test(int n) : n_(n)"<<endl; }
Test(const Test& other) { cout<<"Test(const Test& other)"<<endl; }
~Test() { cout<<"~Test()"<<endl; }
void* operator new(size_t size)// operator new重载
{
cout<<"void* operator new(size_t size)"<<endl;
void* p = malloc(size);
return p;
}
void operator delete(void* p)
{
cout<<"void operator delete(void* p)"<<endl;
free(p);
}
void operator delete(void* p, size_t size)
{
cout<<"void operator delete(void* p, size_t size)"<<endl;
free(p);
}
//跟踪new调用
void* operator new(size_t size, const char* file, long line)
{
cout<<file<<":"<<line<<endl;
void* p = malloc(size);
return p;
}
//跟踪delete调用
void operator delete(void* p, const char* file, long line)
{
cout<<file<<":"<<line<<endl;
free(p);
}
void operator delete(void* p, size_t size, const char* file, long line)
{
cout<<file<<":"<<line<<endl;
free(p);
}
//placement new重载
void* operator new(size_t size, void* p)
{
return p;
}
void operator delete(void *, void *)
{
}
int n_;
};
void* operator new(size_t size)
{
cout<<"global void* operator new(size_t size)"<<endl;
void* p = malloc(size);
return p;
}
void operator delete(void* p)
{
cout<<"global void operator delete(void* p)"<<endl;
free(p);
}
void* operator new[](size_t size)
{
cout<<"global void* operator new[](size_t size)"<<endl;
void* p = malloc(size);
return p;
}
void operator delete[](void* p)
{
cout<<"global void operator delete[](void* p)"<<endl;
free(p);
}
int main(void)
{
Test* p1 = new Test(100); //1、new operator = operator new(分配内存) + 构造函数的调用
delete p1;
char* str = new char[100]; //2、operator new
delete[] str;
char chunk[10];
Test* p2 = new (chunk) Test(200); //operator new(size_t, void *_Where)
//3、placement new,不分配内存 + 构造函数的调用
cout<<"p2->n_:"<<p2->n_<<endl;
//chunk不是堆内存,不能delete,此时需要显式调用析构函数
p2->~Test();
Test* p3 = (Test*)chunk;//和下面操作等价
//Test* p3 = reinterpret_cast<Test*>(chunk);
cout<<"p3->n_:"<<p3->n_<<endl;
//查看new调用位置,方便调试
Test* p4 = new(__FILE__, __LINE__) Test(300);
//#define new new(__FILE__, __LINE__) Test* p4 = new Test(300);
//Test* p4 = new Test(300);
delete p4;
return 0;
}
打印结果: