一、类型转换运算符

必须是成员函数,不能是友元函数
没有参数
不能指定返回类型
函数原型: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
 
#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_

 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
 
#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;
}

 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
 
#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++编程规范

类型转换运算符、*运算符重载、->运算符重载、operator new 和 operator delete的更多相关文章

  1. C++ Primer : : 第十四章 : 重载运算符与类型转换之类型转换运算符和重载匹配

    类型转换运算符 class SmallInt { public: SmallInt(int i = 0) : val(i) { if (i < 0 || i > 255) throw st ...

  2. c/c++ 重载运算符 类型转换运算符

    重载运算符 类型转换运算符 问题:能不能把一个类型A的对象a,转换成另一个类型B的对象b呢?? 是可以的.这就必须要用类型A的类型转换运算符(conversion operator) 下面的opera ...

  3. [C++ Primer] : 第14章: 重载运算符与类型转换

    基本概念 重载运算符是具有特殊名字的函数: 它们的名字由关键字operator和其后要定义的运算符号共同组成. 重载运算符函数的参数数量与该运算符作用的运算对象数量一样多. 对于二元运算符来说, 左侧 ...

  4. 【C++】C++中重载运算符和类型转换

    输入输出运算符 输入输出运算符 输入输出运算符 算术和关系运算符 相等运算符 关系运算符 赋值运算符 复合赋值运算符 下标运算符 递增和递减运算符 成员访问运算符 函数调用运算符 lambda是函数对 ...

  5. C++ Pirmer : 第十四章 : 重载运算符与类型转换之函数调用运算符与标准库的定义的函数对象

    函数调用运算符 struct test { int operator()(int val) const { return (i > 0 ? i : -i); } }; 所谓的函数调用就是一个类重 ...

  6. C++ Primer : 第十四章 : 重载运算与类型转换之重载运算符

    重载前须知 重载运算符是特殊的函数,它们的名字由operator和其后要重载的运算符号共同组成. 因为重载运算符时函数, 因此它包含返回值.参数列表和函数体. 对于重载运算符是成员函数时, 它的第一个 ...

  7. [置顶] operator overloading(操作符重载,运算符重载)运算符重载,浅拷贝(logical copy) ,vs, 深拷贝(physical copy)

    operator overloading(操作符重载,运算符重载) 所谓重载就是重新赋予新的意义,之前我们已经学过函数重载,函数重载的要求是函数名相同,函数的参数列表不同(个数或者参数类型).操作符重 ...

  8. operator重载运算符

    1.重载运算符的函数一般格式如下 函数类型    operator  运算符名称    (形参表列) {对运算符的重载处理} 例如,想将"+"用于Complex(复数)的加法运算, ...

  9. C++ operator重载运算符和隐式转换功能的实现

    C++ operator重载运算符和隐式转换功能的实现: #include <iostream> using namespace std; class OperatorTest { pub ...

随机推荐

  1. 获取 ext grid 选中行 对象

    在ext grid 中如何确定选中行?如何获取选中行数据? 其实很简单,用到了Ext.getCmp('id'),他可以获取到指定id的对象. grid 获取行对象: var row = Ext.get ...

  2. 无线遥控器方案 Si4010/Si4012

    Si4010包含一个嵌入式兼容8051微控制器(MCU),内具4 kB的RAM.8 kB的一次性编程(OTP)非易失性内存.一个128位EEPROM以及用于函数库(library)功能的12 kB R ...

  3. EatCam Webcam Recorder Pro

    EatCam Webcam Recorder Pro Webcam Recorder records webcams to AVI, FLV, WMV files and watch them whe ...

  4. git hub的GUI软件配置与使用

    1. 安装两个软件 1. git的命令行程序--git for windows:http://git-scm.com/download/win 2. git的GUI程序--tortoisegit:ht ...

  5. 用 Redis 实现分布式锁(分析)

    文章转自:http://www.jeffkit.info/2011/07/1000/ Redis有一系列的命令,特点是以NX结尾,NX是Not eXists的缩写,如SETNX命令就应该理解为:SET ...

  6. Android:手把手带你深入剖析 Retrofit 2.0 源码

    前言 在Andrroid开发中,网络请求十分常用 而在Android网络请求库中,Retrofit是当下最热的一个网络请求库 今天,我将手把手带你深入剖析Retrofit v2.0的源码,希望你们会喜 ...

  7. [Android Studio] Android Studio移除的Module如何恢复(转载)

    如果你执行了从module列表中移除module的操作,但是没有执行delete module文件夹的操作,那如何恢复被移除掉的module呢. 关于如何移除请戳这:Android Studio如何删 ...

  8. Git分布式开发之生成ssh公钥

    1.在Preferences>Network Connections>SSH2,切换至Key Management面板,点击 2.点击生成Genarate RSA Key,并修Commne ...

  9. 在Qt示例项目的C ++ / QML源中的//! [0]的含义是什么?

    在Qt示例项目的C ++ / QML源中的//! [0]的含义是什么? 例如:  //! [0] GLWidget :: GLWidget(Helper * helper,QWidget * pare ...

  10. 设计模式实例(Lua)笔记之四(Builder 模式)

    1.描写叙述:      又是一个周三,快要下班了,老大突然又拉住我,喜滋滋的告诉我"牛叉公司非常惬意我们做的模型,又签订了一个合同,把奔驰.宝马的车辆模型都交给我我们公司制作了,只是这次又 ...