一、类型转换运算符重载
一般基本数据类型可以通过转换构造函数转换成类类型,但是类类型不能直接转换为基本数据类型。这些是数据类型转换的一般原则:简单类型一般可以转换成复杂数据类型,但是复杂数据类型一般不能直接转换为基本数据类型。这个时候就需要我们重载类型转换运算符。类型转换运算符可以实现从 类类型->自定义数据类型 的转换。和构造函数 自定义数据类型->类类型 的转换方向正好相反。
我们改进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 newdelete[] 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;
}
打印结果: