首页
社区
课程
招聘
[原创]解决C++“在构造函数中调用构造函数”的问题
发表于: 2013-7-12 14:46 14605

[原创]解决C++“在构造函数中调用构造函数”的问题

2013-7-12 14:46
14605

函数的重用可以大大减少代码量,但是C++构造函数比较特别,“在构造函数中调用构造函数”常常被认为是不可行的,今天花了几个小时解决了这个问题。
下面分析问题来由:
#include <iostream>
using namespace std;
class CNestedConst
{
public:
       int m_iData;
     CNestedConst(int iData): m_iData(iData) {}
       CNestedConst() { //无参数的构造函数
       CNestedConst(0); //调用另一构造函数,用0初始化m_iData
     };
     ~ CNestedConst(){//这个析构函数主要是用来debug
       cout<<"对象地址:"<<this<<endl;
         cout<<"成员变量值:"<<this->m_iData<<endl;
     }
};
int main()
{
       CNestedConst ncTest; //调用CNestedConst()
       cout<<"ncTest.m_iData="<<ncTest.m_iData<<endl ;  //按照设计者的意图,这里应该输出 0 。
       return 0;
}
运行结果:
 

从图中可以看出cout<<"ncTest.m_iData="<<ncTest.m_iData<<endl ;这句代码输出结果是
ncTest.m_iData=-858993460,而析构函数调用了两次,也就是说产生了两个对象。

所以代码段
 CNestedConst() { //无参数的构造函数
 CNestedConst(0); //调用另一构造函数,用0初始化m_iData   };
达不到期望的作用,CNestedConst(0);只是创建了一个临时对象,在CNestedConst()结束后,该对象便析构了,m_iData仍未被赋值。
于是有人断言:不能在构造函数中调用构造函数。

解决这个问题的关键是不能让CNestedConst(0); 产生新对象。

于是很自然的,想到使用this 来调用该函数,写出如下代码
CNestedConst() { //无参数的构造函数
       this->CNestedConst(0); //调用另一构造函数,用0初始化m_iData
     };
一编译,错误又来了VC提示“illegal as right side of '->' operator”
VC把函数名CNestedConst 当做类名了。
遂加上CNestedConst:: 修饰符,以表明这是个函数。
完整代码如下:
#include <iostream>
using namespace std;
class CNestedConst{
public:
       int m_iData;
     CNestedConst(int iData): m_iData(iData) {}
       CNestedConst() { //无参数的构造函数
       this->CNestedConst::CNestedConst(0); //调用另一构造函数,用0初始化m_iData
     };
     ~ CNestedConst(){
       cout<<"对象地址:"<<this<<endl;
         cout<<"成员变量值:"<<this->m_iData<<endl;
     }
};
int main(){
       CNestedConst ncTest; //调用CNestedConst()
       cout<<"ncTest.m_iData="<<ncTest.m_iData<<endl ;  
       return 0;
}
运行结果: 
可见,预期的目的达到了,只产生了一个有效对象。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 5
支持
分享
最新回复 (24)
雪    币: 952
活跃值: (1821)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
c++11支持构造函数重用
2013-7-12 15:15
0
雪    币: 239
活跃值: (190)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
第一种,不是两个对象
2013-7-12 15:57
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
4
是啊,不过VC6不支持,很多人还是用C++98
2013-7-12 16:29
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
5
为何不是?愿闻其详。两个地址是不同的。
2013-7-12 16:30
0
雪    币: 541
活跃值: (654)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
6
Look 一下
2013-7-12 16:47
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
7
升级到 vs 2012 吧。
2013-7-12 17:04
0
雪    币: 18
活跃值: (24)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
呵呵,欣赏一下。
2013-7-12 17:42
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
9
呵呵,这里只是提供一个编程方法而已,就算不在构造函数内调用构造函数,也还有很多变通的方法来实现目标功能,正如实现数据封装不一定要用C++的类,只是用它就方便点而已。
2013-7-12 20:25
0
雪    币: 12
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
楼主牛人,学习了
2013-7-12 20:35
0
雪    币: 12
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
目测不是版本问题,lz的代码在2012里面也是同样的情况
2013-7-12 20:37
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
12
呵呵,共同学习而已,离牛人还远。
2013-7-13 01:50
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
13
谢谢欣赏哈
2013-7-13 01:51
0
雪    币: 153
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
学习了,谢谢!
如果有构造函数重载的,我一般是写一个 CommonConstruct 函数,各个构造函数都调用这个
2013-7-18 16:56
0
雪    币: 517
活跃值: (84)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
15
网上有new(this)CNestedConst()这样更优雅的办法。说是this->CNestedConst::CNestedConst()这样的调用只适用于VC。。。
2013-8-31 10:14
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
16
谢谢告知,确实简洁了。
2013-8-31 15:16
0
雪    币: 209
活跃值: (143)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
太好了,以前只是以为C++的构造函数不能调用其他构造函数,根本没去多想,认为这是语法的特性而已。难得楼主有这种怀疑和专研的精神,才发现了这个新语法(反正我是第一次得知),感谢楼主
2013-8-31 19:28
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
18
不客气。不过我今天才知道原来已经有人用形如 new(this)Constructor() 这样的方式来调用了,有点遗憾。。。人嘛,都想当一次第一。呵呵。
2013-8-31 23:03
0
雪    币: 245
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
谢谢楼主分享
2013-9-1 00:03
0
雪    币: 274
活跃值: (46)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
20
你描述的这种情况在C++中叫隐式类型转换,你传了一个0进去,编译器发现你有一个可以接受int类型的构造函数,于是给你自动把0转型成CNestedConst,解决这个问题最好的办法是在初始化列表里:
CNestedConst()
:CNestedConst(0) //用有参数的构造函数初始化对象
{
      
};
2013-10-15 17:33
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
21
其实我这种方法是显式调用,不涉及到类型转换(如果你愿意可以再仔细看一遍帖子),灵活性就是可以多次、在任意地方调用。你说的方法只能在列表里调用一次,并且只有高版本的c++(如C++11)才支持这种调用。
2013-10-15 17:51
0
雪    币: 274
活跃值: (46)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
22
这个不是你说显示调用就是显示调用,这种语法编译器是会认为你要将0转型为类型,请站在机器的角度考虑问题。
2013-10-15 18:31
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
23
好吧,不跟你争了。建议你找个真正对C++有研究的人来看看这到底是显式还是隐式。
2013-10-15 19:05
0
雪    币: 274
活跃值: (46)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
24
建议你看一下 more effective c++ 的 Item M5,另外这种语法确实是生成匿名对象的语法,而不是调用构造函数。
2013-10-15 20:48
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
25
表示无语。明白人自然一眼能看出来,固执的人也没必要争论了。
2013-10-15 23:11
0
游客
登录 | 注册 方可回帖
返回
//