文中一系列思考和内容引发自以下问题:
我需要在一个类的构造函数中调用另一个对象的构造函数,并使用this初始化其中的一个引用成员。

主要遇到的问题:

1. 构造函数的初始化列表中能访问this吗?

很明显c++创建一个对象分为两部分,创建内存和调用构造函数。
显然在初始化列表中,当前对象占用的内存已经创建好了,ok,this是可以访问的,只是其中的某些成员是没有初始化的(因为没有构造函数还没执行完,只能说对象是部分有效的)。

那也间接说明一个问题,在构造函数的函数体中使用this是完全可靠的,所有编译器可以自动初始化的成员都完成了初始化(比如基类的成员、带有默认构造函数的成员,注意具体初始化顺序是由类成员定义顺序确定的),但当前类的部分未在初始化列表中初始化的且没有默认构造函数类成员变量(比如常见的c++内置类型,int、float、指针等)的值是未定义的。

2. 构造函数参数与成员同名

构造函数的形式如下:带有一个和类成员同名的参数。打印输出只是为了验证成员变量是否初始化。

class A
{
public:
A(int a): a(a){cout<<a<<endl;}
private:
int a;
};

由于初始化列表中不能直接出现this,所以编译器会处理这种重名的情况。也就说,你不能在构造函数的初始化列表中显式用this做限定符,比如下面代码是无法通过编译的:

A:this->a(a){}

3. 如何在一个类的构造函数汇中调用另一个构造函数

构造函数是不允许嵌套调用的,但可以调用不同的重载形式。比如下面代码:(注意这是一道面试题目)

struct CLS
{
int m_i;
CLS( int i ) : m_i(i){}
CLS(){CLS();}
};
int main()
{
CLS obj;
cout << obj.m_i << endl;
return ;
}

输出是多少?

---------------------------------------------------------------------------

答案是未知,因为m_i是未初始化的变量,是个野值。

"CLS(0);"的语句表示创建一个临时的CLS对象,并把该对象的成员m_i初始化为0。当前对象的值并没有初始化。

如果需要实现构造函数类调用另一个构造函数,需要借助于placement new运算符。代码如下:

struct CLS
{
int m_i;
CLS( int i ) : m_i(i){}
CLS()
{
new (this)CLS();
}
};

如果你对placement new不了解,建议看看c++ primer或者TCPL。

在c++11中可以直接通过委托或继承构造函数的形式实现上面功能。

struct CLS
{
int m_i;
CLS( int i ) : m_i(i){}
CLS():CLS(){}
};

4. 解决方案

写到这里。我对于构造函数的初始化列表中引用this的情况基本了解,可以用下面代码解决本文开始提出的问题。

class Context;
class Ref
{
public:
Ref(Context&context):context(context){}
private:
Context &context;
};
class Context
{
public:
Context():ref(*this){}
private:
Ref ref;
};

复述下开始的问题:我需要在一个类的构造函数中调用另一个对象的构造函数,并使用this初始化其中的一个引用成员。

类Context会在其构造函数的初始化列表中通过this调用Ref的构造函数。

5. 参考资料

[1] 从一道题谈C++中构造函数调用构造函数    http://www.cnblogs.com/chio/archive/2007/10/20/931043.html

[2] c++ 一个构造函数 调用 另一个 构造函数    http://www.cnblogs.com/ayanmw/archive/2012/08/20/2647808.html

关于构造函数和this调用的思考的更多相关文章

  1. 尝试解决在构造函数中同步调用Dns.GetHostAddressesAsync()引起的线程死锁

    (最终采用的是方法4) 问题详情见:.NET Core中遇到奇怪的线程死锁问题:内存与线程数不停地增长 看看在 Linux 与 Windows 上发生线程死锁的后果. Linux: Microsoft ...

  2. C++构造函数的自动调用(调用一个父类的构造函数,有显性调用最好,否则就默认调用无参数的构造函数)——哲学思想:不调用怎么初始化父类的成员数据和VMT?

    我总是记不住构造函数的特点,关键还是没有领会那个哲学思想:父类的构造函数一方面要初始化它自己的成员数据,另一方面也要建立它自己的VMT呀!心里默念一百遍:一定调用父类构造函数,一定调用父类构造函数,一 ...

  3. C++类继承中的构造函数和析构函数 调用顺序

    思想: 在C++的类继承中,构造函数不能被继承(C11中可以被继承,但仅仅是写起来方便,不是真正的继承) 建立对象时,首先调用基类的构造函数,然后在调用下一个派生类的构造函数,依次类推: 析构对象时, ...

  4. JavaScript中以构造函数的方式调用函数

    转自:http://www.cnblogs.com/Saints/p/6012188.html 构造器函数(Constructor functions)的定义和任何其它函数一样,我们可以使用函数声明. ...

  5. C++构造函数中不能调用虚函数

    在构造函数中调用虚函数,并不会产生多态的效果,就跟普通函数一样. c++ primer 第四版中497页15.4.5构造函数和析构中的虚函数讲到,如果在构造函数或析构函数中调用虚函数,则运行的是为构造 ...

  6. java中父类与子类, 不同的两个类中的因为构造函数由于递归调用导致栈溢出问题

    /* 对于类中对成员变量的初始化和代码块中的代码全部都挪到了构造函数中, 并且是按照java源文件的初始化顺序依次对成员变量进行初始化的,而原构造函数中的代码则移到了构造函数的最后执行 */ impo ...

  7. 关于预测io调用的思考

    什么是预测io 预测io是linux2.6版本内核调用默认的调用程序,对应用程序进行跟踪,统计应用程序使用io情况,在读操作返回之前先停顿6ms时间(linux默认时间),如果这期间有读操作过来,可以 ...

  8. 转:C++何时调用构造函数,何时调用析构函数

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/wjf1997/article/detai ...

  9. 关于父类私有属性在子类构造函数中super调用的解释

    package test; public class Car { private int carMoney; //汽车租金 private String carName; //汽车名字 private ...

随机推荐

  1. spring加载jar包中多个配置文件(转)

    转自:http://evan0625.iteye.com/blog/1598366 在使用spring加载jar包中的配置文件时,不支持通配符,需要一个一个引入,如下所示: Java代码 <co ...

  2. mvc area出现“找到多个与名为“Home”的控制器匹配的类型”错误的解决方法

    出现该问题的原因是在默认的Golbal.asax.cs文件中已经注册了默认路由 public class MvcApplication : System.Web.HttpApplication    ...

  3. U盘启动装完系统后 一拔下优盘 就不能进入系统

    PE下Ghost安装的,装好进入系统正常,可是拔下 u盘就进不去系统,而插上 u盘就好好的 原因:引导的事,找到本地硬盘第一分区并且激活! 就可以了! 可用下“电脑店-修复主引导记录(MBR)工具”h ...

  4. MongoDB学习笔记(2)

    MongoDB 创建数据库 语法 MongoDB 创建数据库的语法格式如下: use DATABASE_NAME 如果数据库不存在,则创建数据库,否则切换到指定数据库. 实例 以下实例我们创建了数据库 ...

  5. Java设计模式(八)----代理模式

    代理模式 1.生活中: 代理就是一个人或者一个组织代表其它人去做一件事的现实生活中的. 在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象能够在client和目标对象之间起到中介的作用. ...

  6. 15. 使用Apache Curator装饰ZooKeeper

    Apache ZooKeeper是为了帮助解决复杂问题的软件工具,它可以帮助用户从复杂的实现中解救出来. 然而,ZooKeeper只暴露了原语,这取决于用户如何使用这些原语来解决应用程序中的协调问题. ...

  7. 实用的php购物车程序

    实用的php教程购物车程序以前有用过一个感觉不错,不过看了这个感觉也很好,所以介绍给需要的朋友参考一下. <?php//调用实例require_once 'cart.class.php';ses ...

  8. 第一篇:初识ASP.NET控件开发_第三节:“生死有序”的控件生命周期

    一.Page本质是一个Control 我们首先要澄清的第一个概念是页面类Page本质是一个控件类,它派生于TemplateControl类,而TemplateControl派生自Control类.既然 ...

  9. 章节0:MySQl学前知识储备

    一.数据库基础: 1.数据库(database):保存有组织的数据的容器(通常是一个文件或一组文件). 2.数据库管理系统(DBMS):创建和操纵数据库的软件系统. 3.表(table):某种特定类型 ...

  10. 【转载】web网站css,js更新后客户浏览器缓存问题,需要刷新才能正常展示的解决办法

    原文:http://blog.csdn.net/csdn100861/article/details/50684438 问题描述 部署到服务器后访问发现页面展示不正常,但是刷新之后就会展示正常. 问题 ...