C++Primer学习笔记(代码重用)

 在一个自定义的类中,如果这个类的成员里面包含了其他类的对象,就说明这个类是包含了其他类对象成员的类。包含关系和继承关系不同,包含关系只是包含了其成员对象的实现,但是没有包含这个对象所能够调用的它所属类的方法。如果我想要调用这些方法的话,要在自定义类中的成员方法里添加调用这些方法的语句。

1、初始化被包含的对象成员 

在初始化类中成员的时候,可以用成员初始化列表来完成操作,初始化内置类型和其他类对象类型的成员都直接使用成员名(值)这种形式即可,他们会自动调用相应类中的合适的构造函数,但是在初始化有继承的对象的时候,就要在成员初始化列表里面利用作用域标识符的形式调用基类的构造函数。如果在类的构造函数中没有使用成员初始化列表的方式来初始化类中类对象类型的成员的话,那么C++在初始化这些成员时就会调用他们类中的默认的构造函数来初始化他们。


成员初始化列表中的初始化顺序,与在初始化 列表中的顺序没有关系,和他们在类中声明的顺序有关系。


2、使用被包含对象成员的接口

新定义类中的数据成员都被放在类私有部分中,这些成员中的类对象的成员的接口也变得不是公有的,但是却可以在自己定义的类方法中使用这些对象成员所在类的接口。


3、私有继承

私有继承意味着基类当中所有的数据成员还有公有接口在子类中都变成了私有的,所以在子类中,只能通过子类的公有方法去访问私有部分。私有继承和包含对象类型的成员一样,都是只获得对象的实现,但是不获得对象的接口,也就是不能把对象的方法作为我们新定义的类的公有方法。私有继承和包含一个类对象成员都不能够直接调用对象的方法,要通过新定义类中的成员方法才可以进行调用。


包含对象成员是显式的包含了一个有名字的类对象成员,但是私有 继承将会包含一个无名称的对象成员。在新定义类中的构造函数的实现时,在初始化类对象的成员,如果是包含的,那么可以直接使用成员名(值)的方式,编译器会自动为我们调用该对象对象的构造函数,但是如果是私有继承的话,那么就只能够显式的调用相应的构造函数了。


在包含对象的时候,可以在新定义类中的公有方法中使用对象名来调用该对象所在类的公有方法,在私有 继承的时候,由于私有继承包含的是无名的对象成员,所以我们想要调用基类的方法的 时候,可以使用作用域标识符限定的方式来调用。


在私有继承的时候,基类当中的方法只能够在派生类 中的公有方法中使用。如果我想在派生类外中使用的话,我可以吧基类中要使用的方法,放在子类中定义的一个公有方法里,或者直接在子类的公有部分利用using指令来引用基类当中的某一个比较特殊的方法。


4、多重继承

  一般来说,多重继承也就是多重公有继承,多重继承会导致子类有多个基类。因为子类继承基类将会继承下来基类对象的部分,假设A是基类,BC两个派生类继承自A,作为基类出现,D继承自B和C两个类,所以在将子类D对象的地址赋值给基类A对象的指针的时候,可能会出现二义性,因为D类对象继承了BC两个类的部分,而BC两个类的对象部分均有A类的部分,所以说,不知道改把哪一部分的基类地址赋值给A类指针。所以这时候就要在D类对象的地址前面进行强制类型转换。



如果一个子类是继承自多个基类,并且这多个基类都有一个共同的基类。那么为了避免 上面出现的最底下的子类 对象有两份基类的对象的拷贝,可以将起始的那个基类声明为虚基类。这样的话,子类对象只包含一个基类对象部分。从本质上讲,第二层的两个基类继承自起始基类的时候,不再各自拥有一份父类对象的部分,而是共享一份父类对象的部分。声明虚基类的时候加上virtual即可,并且在继承这个虚基类的时候也要加上virtual关键字。



单继承多层继承和多继承多层继承的基类构造函数执行方式是不一样的。

单继承多层继承,自顶向下如果有3层的话(A,B,C),那么在创建C类对象的时候,只能在C类构造函数里面的成员初始化列表里面执行B类的构造函数,然后在B类构造函数的成员初始化列表里面执行A类构造函数,也就是说只能够执行相邻的基类的构造函数。但是这一点在多继承多层继承的时候是有错误的。


多继承多层继承(A,BC,D)

因为D继承自BC两个基类,在执行D的构造函数的时候,必然会在成员初始化列表中使用BC两个构造函数,但是在BC两个构造函数的执行的时候因为同时都继承了A,那么在传递同一个参数都想执行A类的构造函数的时候将会没有任何效果,A类将不会理会这两个BC类传进来的参数想执行构造函数的请求,直接执行默认的构造函数。为了避免这种冲突的时候,如果A是虚基类的时候,禁止通过中间的基类传递给他参数执行他的构造函数,因为在构造D类对象之前,或者说在构造任何子类对象之前都必须构造基类对象部分,所以可以在执行D类构造函数的时候,在成员初始化列表里面执行A类的构造函数,并传递参数,否则A类将执行默认的构造函数。这种情况只对虚基类有用,如果用在非虚基类是违法耳朵。


类模板:

可以在对类模板实例化的时候传递多个参数,并且可以为类型参数提供默认值。可以为类模板的类型参数提供默认值,但是不能够为函数模板参数提供默认值。模板的具体化有几种形式,我们一般用的都是默认的隐式实例化,也就是直接声明一个对象然后指出所需要的类型,在不生成这个模板类的对象时,编译器是不会将这个模板类实例化的。但是可以通过显式调用,来使模板类实例化,也就是加上template class 模板名<类型>;这样会在没创建这个模板类实例化之后的类的对象时进行实例化模板类。类模板还有一种实例化的方式就是显示具体实例化,他是为了某一些特殊情况特殊要求而使用的,比如一些类需要的某一个成员方法可能比较特殊,那么就是用这种形式来实例化模板类,这样的话,以后再碰到这种需求也会继续用这种特定的显示具体化来实例化模板类,不会在使用通用的模式了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值