二十、运算符重载(四) Integer类改进、类型转换运算符重载、 ->运算符重载、 new的三种用法、operator new、operator delete重载

一、类型转换运算符重载

一般基本数据类型可以通过转换构造函数转换成类类型,但是类类型不能直接转换为基本数据类型。这些是数据类型转换的一般原则:简单类型一般可以转换成复杂数据类型,但是复杂数据类型一般不能直接转换为基本数据类型。这个时候就需要我们重载类型转换运算符。类型转换运算符可以实现从 类类型->自定义数据类型 的转换。和构造函数 自定义数据类型->类类型 的转换方向正好相反。

我们改进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;
}
打印结果:





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值