加载中
加载中
表情图片
评为精选
鼓励
加载中...
分享
加载中...
文件下载
加载中...
修改排序
加载中...
使用C++实现类似Java的对象引用的做法
acmilan2015/05/16软件综合 IP:四川
我们知道C++是没有引用计数的,用指针可以灵活传递对象却必须手动管理内存,用栈变量可自动管理内存却有生存期限制。其实C++是非常强大的,用C++完全可以实现类似Java的对象引用的。鄙人才疏学浅,写错了请轻喷。

以下代码更改一处,这里是之前采用的代码,有疏漏,多谢@金星凌日 提醒
Kotlin
MyClass &operator=(const MyClass& src) {                                                             cout << "operator=" << endl;     Dispose(); // 【不能处理自赋值情况】     CopyFrom(src);     return *this; }</code></pre><pre data-tag="nkcsource" data-type="pre">// MyRefClass.cpp : 定义控制台应用程序的入口点。 //                #include "stdafx.h"                #include <string.h> #include <stdio.h> #include <iostream> using namespace std;                class MyClass { // 引用类的写法 private:     void CopyFrom(const MyClass& src) {                                                                 cout << "copyfrom" << endl;         if (src.pm_obj != NULL)         {             src.pm_obj->m_refcount++; // 当复制时增加计数并引用源对象             this->pm_obj = src.pm_obj;         }     }     void Dispose() {                                                                 cout << "dispose" << endl;         if (this->pm_obj != NULL)         {             if (--this->pm_obj->m_refcount <=0) 当析构时减少计数             {                 disposedata(); 若计数减少到零则销毁对象                 delete this->pm_obj;                 this->pm_obj = NULL;             }         }     }                        // TODO: 真正的初始化函数(自己写)     void InitData(char *str1){                                                                 cout << "initdata" << endl;         this->pm_obj->resource = new char [strlen(str1)+20];         strcpy(this->pm_obj->resource, str1);     }     // TODO: 真正的析构函数(自己写)     void DisposeData() {                                                                 cout << "disposedata" << endl;         delete [] this->pm_obj->resource;         this->pm_obj->resource = NULL;     }                public:     // Big-3 的固定写法,不用解释     MyClass &operator=(const MyClass& src) {                                                                 cout << "operator=" << endl;         if (&src != this) { // 【更改】不是自赋值的话             Dispose();             CopyFrom(src);         }         return *this;     }     MyClass(const MyClass& src) {                                                                 cout << "copy" << endl;         CopyFrom(src);     }     ~MyClass() {                                                                 cout << "delete" << endl;         Dispose();     }     // 构造函数写法     MyClass() {                                                                 cout << "new()" << endl;         this->pm_obj = new MyClassBase; // 新建对象并将计数置为1         this->pm_obj->m_refcount = 1;         InitData("");     }     MyClass(char *str1) {                                                                 cout << "new(str)" << endl;         this->pm_obj = new MyClassBase; // 新建对象并将计数置为1         this->pm_obj->m_refcount = 1;         InitData(str1);     }                    // Dup函数(传统复制函数)可以不写     MyClass Dup() {                                                                 cout << "dup" << endl;         MyClass temp(this->pm_obj->resource); // 新建一个完全独立的对象并返回         return temp;     }                    // TODO: 此处添加其它成员函数以方便调用     char *GetString() {         return this->pm_obj->resource;     }                    void *GetData() {         return this->pm_obj;     }                    int GetCount() {         return this->pm_obj->m_refcount;     }                private:     // 引用类的变量仅此一份     struct MyClassBase{         int m_refcount;                        // TODO: 此处添加常规变量以方便保存状态         char *resource;                    } *pm_obj; };                               int _tmain(int argc, _TCHAR* argv[]) {     // 测试程序     MyClass a;     MyClass b = a;     MyClass c;     c = b;     MyClass d=b.Dup();     printf("%p %p %p %p\n",a.GetData(), b.GetData(), c.GetData(), d.GetData());     printf("%p %p %p %p\n",a.GetString(), b.GetString(), c.GetString(), d.GetString());     printf("%d %d %d %d\n",a.GetCount(), b.GetCount(), c.GetCount(), d.GetCount());     return 0; }</=0)></iostream></stdio.h></string.h>// MyRefClass.cpp : 定义控制台应用程序的入口点。 //                #include "stdafx.h"                #include <string.h> #include <stdio.h> #include <iostream> using namespace std;                class MyClass { // 引用类的写法 private:     void CopyFrom(const MyClass& src) {                                                                 cout << "copyfrom" << endl;         if (src.pm_obj != NULL)         {             src.pm_obj->m_refcount++; // 当复制时增加计数并引用源对象             this->pm_obj = src.pm_obj;         }     }     void Dispose() {                                                                 cout << "dispose" << endl;         if (this->pm_obj != NULL)         {             if (--this->pm_obj->m_refcount <=0) 当析构时减少计数             {                 disposedata(); 若计数减少到零则销毁对象                 delete this->pm_obj;                 this->pm_obj = NULL;             }         }     }                        // TODO: 真正的初始化函数(自己写)     void InitData(char *str1){                                                                 cout << "initdata" << endl;         this->pm_obj->resource = new char [strlen(str1)+20];         strcpy(this->pm_obj->resource, str1);     }     // TODO: 真正的析构函数(自己写)     void DisposeData() {                                                                 cout << "disposedata" << endl;         delete [] this->pm_obj->resource;         this->pm_obj->resource = NULL;     }                public:     // Big-3 的固定写法,不用解释     MyClass &operator=(const MyClass& src) {                                                                 cout << "operator=" << endl;         if (&src != this) { // 【更改】不是自赋值的话             Dispose();             CopyFrom(src);         }         return *this;     }     MyClass(const MyClass& src) {                                                                 cout << "copy" << endl;         CopyFrom(src);     }     ~MyClass() {                                                                 cout << "delete" << endl;         Dispose();     }     // 构造函数写法     MyClass() {                                                                 cout << "new()" << endl;         this->pm_obj = new MyClassBase; // 新建对象并将计数置为1         this->pm_obj->m_refcount = 1;         InitData("");     }     MyClass(char *str1) {                                                                 cout << "new(str)" << endl;         this->pm_obj = new MyClassBase; // 新建对象并将计数置为1         this->pm_obj->m_refcount = 1;         InitData(str1);     }                    // Dup函数(传统复制函数)可以不写     MyClass Dup() {                                                                 cout << "dup" << endl;         MyClass temp(this->pm_obj->resource); // 新建一个完全独立的对象并返回         return temp;     }                    // TODO: 此处添加其它成员函数以方便调用     char *GetString() {         return this->pm_obj->resource;     }                    void *GetData() {         return this->pm_obj;     }                    int GetCount() {         return this->pm_obj->m_refcount;     }                private:     // 引用类的变量仅此一份     struct MyClassBase{         int m_refcount;                        // TODO: 此处添加常规变量以方便保存状态         char *resource;                    } *pm_obj; };                               int _tmain(int argc, _TCHAR* argv[]) {     // 测试程序     MyClass a;     MyClass b = a;     MyClass c;     c = b;     MyClass d=b.Dup();     printf("%p %p %p %p\n",a.GetData(), b.GetData(), c.GetData(), d.GetData());     printf("%p %p %p %p\n",a.GetString(), b.GetString(), c.GetString(), d.GetString());     printf("%d %d %d %d\n",a.GetCount(), b.GetCount(), c.GetCount(), d.GetCount());     return 0; }</=0)></iostream></stdio.h></string.h>
捕获.png

[修改于 10年1个月前 - 2015/05/17 13:17:05]

来自:计算机科学 / 软件综合
22
 
新版本公告
~~空空如也
1176764177
10年1个月前 IP:北京
768961
我看了几天c++表示不是特难理解啊
为啥都说c++很难学难道是因为mfc么
我反正只是用c++给mcu
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
768965
引用 1176764177:
我看了几天c++表示不是特难理解啊
为啥都说c++很难学难道是因为mfc么
我反正只是用c++给mcu
实际上C++98并不比C语言难多少,C++11有点杂糅的感觉,并且很多东西还用不了,这个比较蛋疼。
MFC难学主要是因为把WinMain给封装起来了,并且有很多特殊的元素,然后想要更高级的操作还要学WinAPI和COM等很多东西。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
1176764177
10年1个月前 IP:北京
768967
引用 acmilan:
实际上C++98并不比C语言难多少,C++11有点杂糅的感觉,并且很多东西还用不了,这个比较蛋疼。
MFC难学主要是因为把WinMain给封装起来了,并且有很多特殊的元素,然后想要更高级的操作还要学WinAPI和COM等很多东西。
98和11标准相差很大??
iar用的是那个标准?
我一般也就是用函数重载还有能随处定义变量这2点
mfc我没学一般不给pc写程序
要学貌似qt比较万金油吧
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
768968
引用 1176764177:
98和11标准相差很大??
iar用的是那个标准?
我一般也就是用函数重载还有能随处定义变量这2点
mfc我没学一般不给pc写程序
要学貌似qt比较万金油吧
C++11向下兼容C++98,不管在哪里用C++98都可以使用,iar应该也支持C++98。
C++11其实是多了一些语法糖,比如lambda表达式、for遍历语法等,然后库的变化比较大。
现在已经发展到C++14了,C++17也在制定中
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
.........
10年1个月前 IP:江西
768969
Qt跨平台优势大。编译器执行标准应该式是可以指定的。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 修改于 10年1个月前 IP:四川
768971
引用 .........:
Qt跨平台优势大。编译器执行标准应该式是可以指定的。
至于GUI框架,我觉得如果只在Windows上用的话,用MFC比较好。跨平台的话,用wxWidget或Qt都是可以的。

对于C++标准的版次,保证代码兼容性比较重要,新的不一定好,很多开源软件直到2009年都在继续支持VC6
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
768976
引用 1176764177:
98和11标准相差很大??
iar用的是那个标准?
我一般也就是用函数重载还有能随处定义变量这2点
mfc我没学一般不给pc写程序
要学貌似qt比较万金油吧
其实windows上的程序,跨平台的只是少数,不然linus要高兴死了。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
1176764177
10年1个月前 IP:北京
769002
引用 acmilan:
其实windows上的程序,跨平台的只是少数,不然linus要高兴死了。
了解了就是看上qt支持linux所以。。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金星凌日
10年1个月前 IP:陕西
769063
我记得C++ Primer里面就有一个例子。
另外,你这个赋值操作符似乎有点问题。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹
10年1个月前 IP:山东
769071
引用 1176764177:
我看了几天c++表示不是特难理解啊
为啥都说c++很难学难道是因为mfc么
我反正只是用c++给mcu
C++语法复杂, :: -> . C#只有 一个 .
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
769099
引用 金星凌日:
我记得C++ Primer里面就有一个例子。
另外,你这个赋值操作符似乎有点问题。
C++ Primer里确实有。。。在第421页
什么问题。。。有问题就是有问题,不要似乎
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金星凌日
10年1个月前 IP:陕西
769100
引用 acmilan:
C++ Primer里确实有。。。在第421页
什么问题。。。有问题就是有问题,不要似乎
你这个赋值操作符不能处理这样的情况:

Other
MyClass a; a=a;
我记得C++里是要考虑这种问题的。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
769101
引用 金星凌日:
你这个赋值操作符不能处理这样的情况:

MyClass a;
a=a;我记得C++里是要考虑这种问题的。
嗯。。。多谢指教
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
769102
更改一处,多谢@金星凌日 提醒
Kotlin
MyClass &operator=(const MyClass& src) {                                                             cout << "operator=" << endl;     if (&src != this) { // 更改的地方         Dispose();         CopyFrom(src);     }     return *this; }</code></pre>
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
769107
引用 acmilan:
嗯。。。多谢指教
C++我是看某人的blog学的,不是看C++ Primer学的,不是太扎实,标准库都不会用→_→
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
769109
引用 张静茹:
C++语法复杂, :: -> . C#只有 一个 .
你可以看看C++/CLI的语法,不忍直视→_→
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
769115
引用 1176764177:
98和11标准相差很大??
iar用的是那个标准?
我一般也就是用函数重载还有能随处定义变量这2点
mfc我没学一般不给pc写程序
要学貌似qt比较万金油吧
另外要是给MCU用的话,STL也是非常好用的
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
张静茹
10年1个月前 IP:山东
769118
引用 acmilan:
你可以看看C++/CLI的语法,不忍直视→_→
C++/CLI的语法一样很难
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
10年1个月前 IP:四川
769120
引用 张静茹:
C++/CLI的语法一样很难
C++/CLI的语法十分混乱和难以理解。。。主要是要兼容C++语言所以搞得很复杂
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金星凌日
10年1个月前 IP:陕西
769179
引用 1176764177:
98和11标准相差很大??
iar用的是那个标准?
我一般也就是用函数重载还有能随处定义变量这2点
mfc我没学一般不给pc写程序
要学貌似qt比较万金油吧
实际上Qt使用的并不完全是C++。使用Qt的源代码要经过moc处理才可以交给C++编译器编译。

至于C++98和C++11的差别,一本介绍C++11新增内容的书就已经接近300页了。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
1176764177
10年1个月前 IP:北京
769225
引用 金星凌日:
实际上Qt使用的并不完全是C++。使用Qt的源代码要经过moc处理才可以交给C++编译器编译。

至于C++98和C++11的差别,一本介绍C++11新增内容的书就已经接近300页了。
只要向下兼容就好说。。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,6年4个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的