C++ 对象

来源:互联网 发布:网络pos支付平台 编辑:程序博客网 时间:2024/06/06 03:54

类型

大家平常写的,内置类型,class , struct 类型, 类型到底是什么呢?
其实类型就是一个标签,这个标签规定了相应的变量占据了多大的空间。

虚表

虚表分俩个,一个虚函数表一个虚基类表。这俩个表在编译期间,由编译期构造出来,并在构造对象时,将该表的地址赋值给 相应对象的 vptr。
每一个类都有一张专属的虚表,所以一个类的所有对象公用一张虚表,该虚表其实就是一个const 的对象,要么它里面存了虚函数的地址,要么它里面存了虚基类的偏移量。

struct / class 关键字

事实上,这俩个关键字并无差距,struct 与 class 的唯一差别在于默认的访问属性不同,并且class的真正访问属性是由自己本身而决定的,即使其后用 extern struct 做声明,也不起效果。
并且在class中,成员的初始化顺序,同一区段的成员初始化顺序为声明顺序,不同区段的成员初始化顺序是未定义的。(区段指 同一 权限修饰符 public: 下)

class A{   A()   {}}extern struct A;

多态的意义

在C++中有3种设计模式,第一种程序模式(C的方式写代码)
第二种设计,ADT(即一个类的成员变量+成员函数)
第三种,面向对象(多态,同一个接口,不同的对象显示不同的结果)
  多态其实就是为了,当在继承链中新增加一个派生类时,这个派生类只用实现自己的函数,不用写出在继承链中所有自定义类型共通的函数,这个其实就是多态的意义。
  它就是为了面向对象而生,即使一个基类对象以一个派生类对象为初始值,发送了对象切割,那此时该对象本身是基类,调相应的函数是不会发送多态的。其实这就是多态,为了面向对象而生。
  那当以指针/引用调用时会引发多态,这其实又是面对对象的思想,指向不同对象调用不同虚函数。

class Base{ void virtual Fun() {} } class Dervied : public Base  {   void Fun()   {} }  Dervied d;  Base b = d;  b .Fun() ;  Base :: Fun()  并不会发送多态,这其实因为编译器把基类对象的vptr置向了基类的虚表,没有把它置向派生类的虚表而造成的。

多态/非多态类的优缺点

非多态优点

无额外空间开销
调用快(一是类成员函数多以 inline展开,而虚函数是没办法内联的)

非多态缺点

无弹性,写一个函数就写死了,扩展性不好。

多态优点

提高同一接口,面向不同的对象,展示出不同的结果,弹性好。

多态缺点

调用慢,浪费空间

构造函数/copy构造函数

构造函数

在我刚学c++的时候,我一直记住一句话,当你没写任何构造函数/拷贝构造函数的时候,编译期会为你合成构造函数。其实这个是错误的,只有当编译期认为需要合成一个有用的构造函数的时候才会为你合成。

默认构造会合成的场景

1.当成员变量中有自定义类时,该成员又有默认构造的时候
2.继承中,基类有默认构造的时候
3.当类内有虚函数的时候
4.当类内有虚拟继承的时候

拷贝构造会合成的时候

1.当类中成员变量,有拷贝构造的时候。
2.当基类有拷贝构造的时候
3.有虚函数
4.有虚拟继承
  对于默认构造来说,没有上述四种情况,生成对象时,直接当成内置类型来处理,定义对象时并无相应的汇编生成。并不会有相应的构造函数调用。
  对于拷贝构造,如果没有上面四种情况是不会合成的,编译期只是做了逐次把每一个成员变量依次赋值而已,并不会调生成拷贝构造并调用。

NRV优化(copy构造的NRV优化)

  当你有显示的copy构造函数时,并在一个函数中定义了一个局部变量,并把这个局部变量返回时,出触发NRV优化,不在调用copy构造而直接把该局部变量返回。

对于 copy 构造什么时候要什么时候不要?

  如果没有太多的需要传回一个临时对象的话并且没有自定义类或者继承的话,就别写了,编译器默认会逐次的浅copy。
  如果有的很多传临时对象返回的场景,还是显示给出吧,为了触发NRV优化(NRV优化已经被列入c++11的标准了)

初始化列表

初始化列表顺序

  这个顺序跟你成员变量的声明顺序有关和初始化列表中的各变量的声明顺序无关,对于继承体系来说,基类先于成员变量初始化。