类型转换运算符、*运算符重载、->运算符重载、operator new 和 operator delete
一、类型转换运算符
必须是成员函数,不能是友元函数
没有参数
不能指定返回类型
函数原型:operator 类型名();
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#ifndef _INTEGER_H_
#define _INTEGER_H_ class Integer { public: Integer(int n); ~Integer(); Integer &operator++(); //friend Integer& operator++(Integer& i); Integer operator++(int n); //friend Integer operator++(Integer& i, int n); operator int(); void Display() const; private: int n_; }; #endif // _INTEGER_H_ |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
#include "Integer.h"
#include <iostream> using namespace std; Integer::Integer(int n) : n_(n) { } Integer::~Integer() { } Integer &Integer::operator ++() { //cout<<"Integer& Integer::operator ++()"<<endl; ++n_; return *this; } //Integer& operator++(Integer& i) //{ // //cout<<"Integer& operator++(Integer& i)"<<endl; // ++i.n_; // return i; //} Integer Integer::operator++(int n) { //cout<<"Integer& Integer::operator ++()"<<endl; //n_++; Integer tmp(n_); n_++; return tmp; } //Integer operator++(Integer& i, int n) //{ // Integer tmp(i.n_); // i.n_++; // return tmp; //} Integer::operator int() { return n_; } void Integer::Display() const { cout << n_ << endl; } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include "Integer.h"
#include <iostream> using namespace std; int add(int a, int b) { return a + b; } int main(void) { Integer n(100); n = 200; n.Display(); int sum = add(n, 100); cout << sum << endl; int x = n; int y = static_cast<int>(n); return 0; } |
其中n = 200; 是隐式将int 转换成Interger类;int x = n; 是调用operator int 将Interger 类转换成int,也可以使用static_cast 办到;此外add 函数传参时也会调用operator int 进行转换。
二、->运算符重载
类* operator->();
类& operator*();
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
#include <iostream>
using namespace std; class DBHelper { public: DBHelper() { cout << "DB ..." << endl; } ~DBHelper() { cout << "~DB ..." << endl; } void Open() { cout << "Open ..." << endl; } void Close() { cout << "Close ..." << endl; } void Query() { cout << "Query ..." << endl; } }; class DB { public: DB() { db_ = new DBHelper; } ~DB() { delete db_; } DBHelper *operator->() { return db_; } DBHelper &operator*() { return *db_; } private: DBHelper *db_; }; int main(void) { DB db; db->Open(); db->Query(); db->Close(); (*db).Open(); (*db).Query(); (*db).Close(); return 0; } |
db->Open(); 等价于 (db.operator->())->Open(); 会调用operator-> 返回DBHelper类的指针,调用DBHelper的成员函数Open()。这样使用的好处是不需要知道db 对象什么时候需要释放,当生存期结束时,会调用DB类的析构函数,里面delete db_; 故也会调用DBHelper类的析构函数。
(*db).Open(); 等价于(db.operator*()).Open();
三、operator new 和 operator delete
在前面曾经提过:实际上new 有三种用法,包括operator new、new operator、placement new,new operator 包含operator new,而placement new 则没有内存分配而是直接调用构造函数。下面看例子:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
#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) { cout << "void* operator new(size_t size)" << endl; void *p = malloc(size); return p; } void operator delete(void *p) //与下面的operator delete函数类似,共存的话优先; { //匹配上面的operator new 函数 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); } /**********************************************************************/ void *operator new(size_t size, const char *file, long line) { cout << " void* operator new(size_t size, const char* file, long line);" << endl; cout << file << ":" << line << endl; void *p = malloc(size); return p; } void operator delete(void *p, const char *file, long line) { cout << " void operator delete(void* p, const char* file, long line);" << endl; cout << file << ":" << line << endl; free(p); } void operator delete(void *p, size_t size, const char *file, long line) { cout << "void operator delete(void* p, size_t size, const char* file, long line);" << endl; cout << file << ":" << line << endl; free(p); } /**************************************************************************/ void *operator new(size_t size, void *p) { cout << "void* operator new(size_t size, void* p);" << endl; return p; } void operator delete(void *, void *) { cout << "void operator delete(void *, void *);" << endl; } /**************************************************************************/ int n_; }; /*************** global **********************************************/ 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); // new operator = operator new + 构造函数的调用 delete p1; char *str1 = new char; delete str1; char *str2 = new char[100]; delete[] str2; char chunk[10]; Test *p2 = new (chunk) Test(200); //operator new(size_t, void *_Where) // placement new,不分配内存 + 构造函数的调用 cout << p2->n_ << endl; p2->~Test(); // 显式调用析构函数 //Test* p3 = (Test*)chunk; Test *p3 = reinterpret_cast<Test *>(chunk); cout << p3->n_ << endl; #define new new(__FILE__, __LINE__) //Test* p4 = new(__FILE__, __LINE__) Test(300); Test *p4 = new Test(300); delete p4; return 0; } |
从输出可以看出几点:
1、new operator 是分配内存(调用operator new) + 调用构造函数
2、operator new 是只分配内存,不调用构造函数
3、placement new 是不分配内存(调用operator new(与2是不同的函数) 返回已分配的内存地址),调用构造函数
4、delete 是先调用析构函数,再调用operator delete.
5、如果new 的是数组,对应地也需要delete [] 释放
注意:
1、如果存在继承或者对象成员,那么调用构造函数或者析构函数时将有多个,按一定顺序调用,参见这里。
2、假设存在继承,delete 基类指针;涉及到虚析构函数的问题,参见这里。
最后还存在一点疑问的是 delete p4 为什么调用的不是 void operator delete(void* p, const char* file, long line); 而是
void operator delete(void* p) ; 希望有明白的朋友告诉我一声。
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范