C++的黑科技(深入探索C++对象模型)

周二面了腾讯,之前只投了TST内推,貌似就是TST面试了

其中有一个问题,“如何产生一个不能被继承的类”,这道题我反反复复只想到,将父类的构造函数私有,让子类不能调用,最后归结出一个单例模式,但面试官说,单例模式作为此题的解答不够灵活,后来面试官提示说,可以用友元+虚继承,可以完美实现这样一个类

当然那时我还不太明白,友元与虚继承我都极少接触过,只是知道有这些东西,回头搜了一下“不能被继承的类”的做法,具体如下:

1,声明一个类,CNoHeritance,构造函数为private,并声明友元类CParent;
2,让CParent虚继承CNoHeritance
这样CParent就成为一个可以被正常实例化,但又不能被继承的类

吴总当时评价说,“呵呵,虚继承,感觉完全是黑科技啊”

这个黑科技真是戳中我笑点,但想到C++经常有些奇妙的东西,现在想总结一下

1,C++构造函数的黑科技

对于阅读过进阶C++书籍的都该知道,编译器会在“需要”的时候,那么什么是需要的时候呢?四种情况:

  • 1,“带有Default Constructor”的Member Class Object
  • 2,“带有Default Constructor”的Base Class
  • 3,“带有至少一个Virtual Function”的Class
  • 4,“带有一个Virtual Base Class”的Class

自动合成的构造函数往往都是public,在派生类中,它的构造函数是可以被使用的,即派生类不会因此受到限制。

那么,如何能使派生类不能使用基类的函数或成员呢?

  • private:只能由:1,该类中的函数;2,其友元函数访问
  • protected:可以被:1,该类中的函数;2,其友元函数;3,派生类(子类)的函数访问
  • public:可以被:1,该类中的函数;2,其友元函数;3,子类的函数;4,该类的对象访问

如果一个类的构造函数声明为private,则其派生类甚至该类的对象都不能访问,意味着两点:

  • 1,该类不能被继承
  • 2,该类不能由系统实例化,即它实例化的对象不会在栈内存上

那么怎么使用该类呢?一般而言,会通过该类的函数来创建

class A
{
private:
    A(){}
public:
    A& createA()
    {
        A* p=new A();
        return *p;
    }
};

然而,这样又引申一个问题:类没有实例化,如何能使用其成员函数呢?

答案是将该成员函数声明为static,这样不需要实例化即可访问,即将上述改为:

class A
{
private:
    A(){}
public:
    static A& createA()
    {
        A* p=new A();
        return *p;
    }
};

A Object=A::createA();

很明显,上面的实例化过程很不方便,简直是艰辛呀,单例模式的其中一种实现就是如此,在此先不讲。这样实现的类,不能被继承,但自己也不好过

so,如果用友元来实现,是怎么实现的呢?

声明一个类,及其友元

class A
{
private:
    A(){}

    friend class B;
};

那么B是可以调用A的private的构造函数的,那么让B虚继承A会发生什么事呢?

由《深度探索C++对象模型》看到,B内存中将有一份A类的实体,调用A的构造函数构造的,这对于友元类B是可行的

class A
{
private:
    A(){}

    friend class B;
};

class B : virtual A
{
};

那么这样的B能不能被继承呢?假设有个类继承了B,如下

class A
{
private:
    A(){}

    friend class B;
};

class B : virtual A
{
};

class C : B
{
};

考虑到虚继承的特性,C也将调用A的构造函数构造出一个A,但!!C并不是A的友元类,所以根本不能执行A私有的构造函数,这段程序,如果不实例化C,编译器不会报错,但一旦实例化C,则将报错。

而B是可以正常实例化的一个类,这样就完美实现了一个不能被继承的类:B

2,C++构造函数初始化列表的黑科技

相比于构造函数的各种trick,C++的初始化列表就显得很容易了,只有那么一点要注意:

C++的初始化列表的赋值顺序,是与C++类里面成员变量的声明顺序相关,与初始化列表里的顺序无关

举个例子,以下就会出现莫名错误:

class A
{
public:
    A(int _x, int _y):y(_y), x(y){}
public:
    int x;
    int y;
};

根据声明顺序,在初始化列表中,是先完成x(y)这个步骤,但此时y并没有被赋值,所以得到的x是个随机的值。

3,C++虚函数的黑科技

C++虚函数的问题,几乎是面试必问,实际上需要了解的东西也挺多,我自己在前几次面试,都有些理解有误的地方,或者理解不够完善

这里总结几点吧(以下类都是针对有虚函数的类):

  • 1,每个类都有虚函数表,这个虚函数表是在编译阶段构建,在代码段产生一个vtbl
  • 2,每次实例化的时候,构造函数在前几个字节,产生一个指向虚函数表的指针,指向代码段的那个虚函数表
  • 3,虚函数的实现与调整,是通过移动或变换虚函数表的指针来实现的。
  • 4,纯虚函数是指只声明,但未被实现的虚函数,具有纯虚函数的类不能被实例化,为抽象类

4,C++拷贝构造函数的黑科技

C++的拷贝构造函数是C++默认的四个函数之一:构造函数、析构函数、赋值函数、拷贝构造函数

拷贝构造函数是一种特别的构造函数,在《深度探索C++对象模型》书中说,有三种情况,会导致拷贝构造函数被触发:

  • 1,以一个object的内容作为另一个class object的初始值

    class X {...}
    X x;
    X xx=x;
  • 2,当object被当作参数传递给某个函数时
    void foo(X x);
    X xx;
    foo(xx);
  • 3,函数传回一个class object的时候
    X foo_bar()
    {
      X xx;
      // ...
      return xx;
    }

一般情况下,如果没有提供explicit copy constructor时,会发生什么呢?

一个良好的编译器可以为大部分class objects产生bitwise copies,因为它们有bitwise semantics...

这里说的很神奇,好像我们不需要自己写copy constructor也没问题一样,实际上,bitwise copies在有些情况下是非常不推崇的

首先解释下什么是bitwise copies:这是指,在拷贝过来的时候,把class的内存直接位拷贝过来,即可以看成是内存拷贝(对应的有值拷贝)

位拷贝有很多问题,典型的一个,如果class里面含有分配内存的指针,那么它会将指针指向的地址直接拷贝过来:

class A
{
public:
    int *p;
};

int main()
{
    A a1;
    a1.p=new int[10];
    A a2=a1;
    cout << a1.p << endl;
    cout << a2.p << endl;
    return 0;
}

这里可以发现,a1.p的地址与a2.p的地址是一样的,那么,我分配的内存,该由哪个释放呢?我释放了,另一个怎么办呢?

实际上,这种拷贝方式在STL的string里面肯定是要重写的,不能用位拷贝。

《深度探索C++对象模型》中,说class不展现出“bitwise copy semantics”有四种情况:

  • 1,当class含有member object并且后者有一个copy constructor(声明或合成)
  • 2,当class继承一个base class 而后者存在一个copy constructor的时候
  • 3,当class声明了一个或多个virtual functions时
  • 4,当class派生自一个继承串链,其中有一个或多个virtual base classes时

其实主要都是担心,指针在bitwise semantics下,随便复制可能会导致不可预料的错误

在这里说一下赋值函数拷贝构造函数在触发上的区别:

当一个object从无到有时,触发的一定是拷贝构造函数,赋值函数只会在已有的object赋值时,才会触发

5,C++虚继承的黑科技

针对虚继承,可以坦承的一点就是

所有简单的东西,遇到虚继承,似乎都要单独拿出来讨论

时间: 2024-12-09 17:28:58

C++的黑科技(深入探索C++对象模型)的相关文章

张书乐:不谈“黑科技”,小米智能音箱卖的是温情

AI和AV,只有一字之差.一个颇为暧昧的名字"小爱同学",带出了小米的智能家居大战略--温暖.这也是起个类似女优或充气娃娃名字的真相. 文/张书乐(人民网.人民邮电报专栏作者) 新著有<微博运营完全自学手册> 7月26日的新品发布会上,著名发布会"表演艺术家"雷军同学发布了一款售价只有 299 元的智能音箱,要唤醒这个音箱,需要喊一声"小爱同学". 结果,这个看似小米空气净化器微缩版的"小爱同学"受到的关注,远比同

360手机f4新体验 安全与黑科技同行

万物复苏的3月,360携360手机f4重归行业前线. 这款主打质价比的新品不仅价格亲民,功能也颇具亮点--在其最低售价仅为599元的价格基础上,360仍然为这款手机搭载了双微信.趣味拍照.应用冷藏室.地理位置穿越.一卡多号等诸多"黑科技"功能,而硬件上搭配金属中框.0.4s速度的指纹解锁等配置,也使得这款售价亲民的手机表现不俗:其他方面,已经日臻纯熟的360 OS,加上360手机此前在多款机型上的做工经验,也在这款手机上得以具体体现.从目前现有情况来看,这款360手机f4无论在价格还是

2017-12-27 每日黑科技

[碧桂园信管中心] [资讯与趋势] 1.如何评价大数据的未来? 收集.处理.分析数据确实是一件有意义的事,并将产生价值,但问题在于,我们能从大数据里离挖掘到多少价值? 大数据是真的炒作大过实际价值还是一些人目光短浅看不到价值? 大数据产业发展的要面临的挑战: 一是对数据资源及其价值的认识不足. 二是技术创新与支撑能力不够. 三是数据资源建设和应用水平不高. 四是信息安全和数据管理体系尚未建立. 五是人才队伍建设亟需加强. 评论:本人认为大数据概念在现阶段依然有炒作大于实际价值的嫌疑,从2010年

AI助力电商狂欢,这些黑科技很多人不知道!

事物在发展的过程中总会受到来自四面八方的非议,人工智能也是如此.在它以良好态势发展的时候,不断有人跳出来唱衰.他们说要实现商业化还要很久,人工智能的泡沫可能说破就破.然而今年的双十一,恰恰给了这些"唱衰派"有力一击. 人工智能的商业化是必然的,而且速度会越来越快.面会越来越宽,双十一电商狂欢就是最好的证明.从设计到客服.从再从分拣到物流,每一个环节都能看到人工智能的身影.就目前的反响来看,人工智能的商业化在电商领域是成功的. 下面,我们就来盘点一下双十一背后的AI黑科技,都系好安全带坐

华为新一代企业数字化协作,有哪些黑科技?

华为在全球170多个国家和地区拥有1023个办公室,这背后正是高效敏捷的数字化IT平台,支撑了全球化高效运营.对于华为来说,高效的沟通与协作在企业的生产过程中发挥着举足轻重的作用,支撑着华为分布在全球超过18万名员工及合作伙伴协作,完成了华为在2017年超过6000亿人民币的销售收入.2018年上半年同比增长达到15%的业绩. 2018年9月,在华为企业通信CloudLink新品发布会上,发布了包括会议终端CloudLink Board.编码器CloudLink Box.专业智能导播CloudL

4大特点解析华为云数据湖“黑科技”

4大特点解析华为云数据湖"黑科技"如果有人问数据湖是什么,我会告诉他们,是"桶装水"的集合.随着企业业务的发展,数据出现井喷,数据量呈几何增长,数据来源和类型更加多元化.传统数据仓库就如同"桶装水商店",已经承载不了全部水体,因此需要一个可以满足存储需求的,新的架构作为大数据的支撑.这就是数据湖.它汇聚不同数据源的溪流,包括大量无序的非结构化数据(文本.图像.声音.网页等).我们把它倒入数据湖,然后开始探索该数据.我们希望这是一个包含所有数据的,

2017黑科技趋势最具看点的十大新品

腾讯数码讯(Human)作为一年一度的全球消费电子市场风向标,今年同样在拉斯维加斯举办的CES 2017消费电子展,依然吸引了一大批全球各个领域的厂商参展,从科技巨头到初创小团队.从传统汽车厂商再到家电企业,似乎所有能与科技沾边的公司都希望能在CES 2017上好好展示一次自己的风采. 其实每年的CES都有一些明星产品给我们留下深刻的印象,今年的也不例外.而这些明星产品不仅仅只是单单一款产品,更是代表了各自行业在进入到2017年之后的一个发展趋势和方向.而就将这样的变化能否成为未来的主流.或只是

今年黑科技趋势最具的五个看点

CES 2017年人工智能引爆全球最火黑科技盛会 CES 2017 1月5日-8日在美国拉斯维加斯举行,数千家企业.几十万人将参与到这次科技的狂欢秀中.本文为埃森哲技术总监带来的关于本年度CES 的5大看点.他认为:人工智能将统治本年度的CES,变得无处不在.另外,他还分析了智能助理.物联网安全.虚拟现实等多个领域在本届大会上的表现. 2017 年国际消费电子展(CES 2017)将于1月5号拉开帷幕,在这个荒漠之城举办为期5天的展会,保守估计会吸引超过177000名参会者. 这也是一年之中唯一

试读—增长黑客,创业公司必知的“黑科技”

概述 刚一看到书名,最引起注意的是黑客两个字,那个带着神秘色彩,让无数程序员羡慕嫉妒恨的角色.但仔细一看,增长黑客,创业公司必知的"黑科技",是讲公司如何以切实的依据.低廉的成本.可控的风险来达成用户增长.活跃度上升.收入额增加等知识及案例的,这对于初创公司又没有充足的资金去燃烧以改变用户习惯的情况无疑是雪中送炭.指北之针. 什么是增长黑客? 本书适合哪些读者? 增长 靠原始积累实现增长的时代已经过去,也不适合互联网.移动互联网.互联网+的模式.我们经常能看到类似的新闻"某公