类型转换运算符、*运算符重载、->运算符重载、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*();
C++ Code
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 则没有内存分配而是直接调用构造函数。下面看例子:
C++ Code
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++编程规范
- 从零开始学C++之运算符重载(四):类型转换运算符、*运算符重载、->运算符重载、operator new 和 operator delete
- 从零开始学C++之运算符重载(四):类型转换运算符、*运算符重载、->运算符重载、operator new 和 operator delete
- 从零开始学C++之运算符重载(四):类型转换运算符、*运算符重载、->运算符重载、operator new 和 operator delete .
- 字符串的运算符重载(如:赋值‘=’、加'+'、加等'+='、下标'[]'相等'=='、不等'!='、大于'>'、输出运算符'<<'以及类型转换)
- 二十、运算符重载(四) Integer类改进、类型转换运算符重载、 ->运算符重载、 new的三种用法、operator new、operator delete重载
- 写一个复数类Complex,(复数形如3.2+5.6i,2.9-1.3i,其中i*i=-1)。要求支持+-*/,++、--,到bool类型和string类型的转换,支持>>、<<运算符。
- error C2678: 二进制“>>”: 没有找到接受“std::istream”类型的左操作数的运算符(或没有可接受的转换)
- C++ 运算符重载和类型转换运算符
- C++类型转换运算符之const_cast<newtype>(expression)
- C2679 二进制“>>”: 没有找到接受“std::string”类型的右操作数的运算符(或没有可接受的转换)
- C++:运算符重载、string类重写、数据类型转换、->操作符重载、virtual继承、virtual函数、typeid
- C++类型转换运算符: static_cast<>,reinterpret_cast<>,dynamic_cast<>, const_cast<>
- C++:运算符重载、string类重写、数据类型转换、->操作符重载、virtual继承、virtual函数、typeid
- :MessageBoxW”: 不能将参数 1 从“const char [5]”转换为“LPCTSTR” 1> 与指向的类型无关;转换要求 reinterpret_cast、C 样式
- C++:关于C++的四个类型转换运算符
- Java 变量,数据类型的转换,若干算术运算符
- <Linux+Qt>char*,QString,String类型的相互转换
- JAVA学习(三):Java基础语法(变量、常量、数据类型、运算符与数据类型转换)
- 二进制"<<"没有找到接收"std:string"类型的右操作数的运算符(或没有可接收的转换)
- 黑马程序员—Java编程基础+常量与变量+类型的转换+进制的转换+运算符+scanner的使用+程序流程结构控制+循环结构