一、学习笔记

1.继承

class Student : public Person {
...
}

2.继承时权限
派生类中可以直接访问父类的protected成员,但是不能访问其private成员,若继承时不写public,默认就是private继承。

继承方式\基类中的访问属性    public        protected        private
public public protected 隔离
protected protected protected 隔离
private private private 隔离

(1) 无论哪种继承方式,在派生类的内部使用父类时并无差别
(2) 不同的继承方式,会影响这两方面:外部代码对派生类的使用,派生类的子类对派生类成员的使用。

3.using更改继承成员的权限
①修改成员变量的
  在派生类中的public:下使用using Father::room_key;可以将父类的protected成员room_key提升为public权限,此时可以直接在main()中访问!
  在派生类中的private:下使用using Father::room_key;可以将父类的protected成员room_key降低为private权限,此时就不可以在类外进行访问!
  若在派生类中可以使用using关键字将父类的public成员降为private权限,这样子类的子类就继承不到这个属性了。
①修改成员函数的
  在派生类中的public:下使用using Father::getRoomKey;可以将父类的protected成员getRoomKey()成员函数提升为public权限。可以直接使用函数名而不是
函数签名的原因是这里仅仅是修改权限,父类重载的所有getRoomKey()都变为public了,之后类外调用根据参数匹配规则不变。

也就是说可以使用using关键字调整继承来的成员的访问权限,但前提是这些成员对你这个类可见。

4.构造函数子类也会继承父类的,但是其构造的是从父类那里继承过来的部分。

5.子类中若是实现了与父类的同名函数getName(),可以Parent::getName()来调用父类的getName(), 但是操作的成员变量是子类继承父类的部分。

6.子类定义与继承来的可见的成员变量同名的成员变量也是可以的。重新定义函数签名和函数名都相同的函数叫做复写。

7.继承的父类的成员函数中操作的成员变量都是子类继承于父类的。父类的成员函数操作的成员变量都是父类的,除非子类进行了复写。

8.在子类的外部可以通过s1.Father::getRoomKey();调用父类的函数,在子类的内部可以通过Father::getRoomKey();调用父类的函数。

9.多重继承

class Sofabed: public Sofa, public Bed {
...
} Sofabed s;
s::Sofa::setWeight() //指明调用Sofa的setWeight()

10.多继承会导致二义性,解决办法是使用虚继承。
解决:把共性的东西提炼出来,只保留一份备份,放在共有的父类Fourniture中,然后Sofa和Bed都虚继承Fourniture。

class Sofa : virtual public Fourniture
class Bed : virtual public Fourniture
class Sofabed: public Sofa, public Bed

11.虚继承内存分布
虚继承的成员在Sofabed类中只会保留一份备份,也就是说Fourniture类中定义的成员只会在SofaBed类中只保留一份。

12.要尽量避免使用多继承,它会使程序变得更加复杂,更容易出错。

13.带有继承和虚继承的构造函数的调用次序
先父后子:
  (1)先调用基类的构造函数
    ①先调用虚拟基类的构造函数,再调用一般基类的构造函数。注意是先把所有虚基类的构造函数执行完后再执行的一般基类的构造函数。
  (2)然后再调用自身的构造函数
    ①先调用对象成员的构造函数,然后再调用自己的构造函数。

对于虚继承的基类,基类的构造函数只执行一次。
eg: 如下两次继承,Furniture和Verication3C,它两个的构造函数是被调用一次!
class Soft : virtual public Furniture, virtual public Verication3C
class Bed : virtual public Furniture, virtual public Verication3C

14.子类的构造函数给父类的构造函数传参数

class LeftRightSofabed : public Sofabed, virtual public LeftRightCom {
private:
Date date;
public:
LeftRightSofabed(char *str1) : Sofabed(str1), LeftRightCom(str1), date(str1) { //注意这里的data用的是成员名,而不是类名
cout <<"LeftRightSofabed()"<<endl;
}
};

试验发现,在子类中使用初始化列表初始化虚继承的类无法触发虚继承的类中的有参构造函数被调用,调用的还是无参构造函数。
eg:上面代码中LeftRightCom()的有参构造函数不会被调用,调用的还是无参构造函数。

二、例子

1.单继承例子

#include <iostream>

using namespace std;

class Father {
private:
int money;
char *name;
protected:
int room_key; int getRoomKey(int) {
cout << "getRoomKey(int) name=" << name << endl;
return room_key;
}
public: int getRoomKey(void) {
cout << "getRoomKey(void) name=" << name << endl;
return room_key;
}
Father() {
money = ;
room_key = ;
name = "father_begin";
cout << "Father()" << endl;
}
Father(char *name) {
this->name = name;
cout << "Father(char *name)" << "name= " << this->name << endl;
}
~Father() {
cout << "~Father()" << endl;
} int getMoney(void) {
cout << "int getMoney(void)" << endl;
return money;
}
void setMoney(int money) {
cout << "void setMoney(int money)" << endl;
this->money = money;
}
}; class Son : public Father {
char *name; public:
using Father::room_key;
using Father::getRoomKey;
Son(char *name){
this->name = name;
cout << "Son()" << "name= " << this->name << endl;
}
~Son() {
cout << "~Son()" << "name= " << this->name << endl;
}
int getRoomKey(void) {
Father::getRoomKey();
cout << "getRoomKey(void) name=" << name << endl;
return room_key;
} }; int main()
{ Son s1("son_name"); s1.getRoomKey();
s1.getRoomKey();
s1.Father::getRoomKey();
s1.getMoney(); cout <<"s1.room_key= "<< s1.room_key << endl; return ;
} /*
Father()
Son()name= son_name
getRoomKey(void) name=father_begin
getRoomKey(void) name=son_name
getRoomKey(int) name=father_begin
getRoomKey(void) name=father_begin
int getMoney(void)
s1.room_key= 1
~Son()name= son_name
~Father()
*/

2.多继承中使用虚继承来处理成员变量二义性问题

#include <iostream>

using namespace std;

class Furniture {
int weight;
public:
int size;
int getWeight() {
cout << "Furniture::getWeight()" << endl;
return weight;
}
}; class Sofa : virtual public Furniture {
int sofa;
public:
void getSofa() {
cout << "Sofa::getSofa()" << endl;
}
}; class Bed : virtual public Furniture {
int bed;
public:
void getBed() {
cout << "Bed::getBed()" << endl;
}
}; class Sofabed : public Sofa, public Bed {
int color;
public:
int getColor() {
cout << "Sofabed::getColor()" << endl;
return color;
} int getSize() {
cout << "Sofabed::getSize()" << endl;
return size;
}
}; int main() { Sofa so;
Bed be;
Sofabed sb; so.getWeight();
so.getSofa(); be.getWeight();
be.getBed(); sb.getSize();
sb.getSofa();
sb.getBed();
sb.getWeight(); return ;
} /*
Furniture::getWeight()
Sofa::getSofa()
Furniture::getWeight()
Bed::getBed()
Sofabed::getSize()
Sofa::getSofa()
Bed::getBed()
Furniture::getWeight()
*/

3.虚继承构造函数中调用父类构造函数的例子

#include <iostream>

using namespace std;

class Furniture {
public:
Furniture() {
cout << "Furniture()" << endl;
}
Furniture(char *abc) {
cout << "Furniture(abc)" << endl;
}
}; class Verication3C {
public:
Verication3C() {
cout << "Verication3C()" << endl;
}
Verication3C(char *abc) {
cout << "Verication3C(abc)" << endl;
}
}; class Soft : virtual public Furniture, virtual public Verication3C {
public:
Soft() {
cout << "Soft()" << endl;
}
Soft(char *abc) : Furniture(abc), Verication3C(abc) {
cout << "Soft(abc)" << endl;
}
}; class Bed : virtual public Furniture, virtual public Verication3C {
public:
Bed() {
cout << "Bed()" << endl;
}
Bed(char *abc) : Furniture(abc), Verication3C(abc){
cout << "Bed(abc)" << endl;
}
}; class SoftBed : public Soft, public Bed {
public:
SoftBed() {
cout << "SoftBed()" << endl;
}
SoftBed(char *abc) : Soft(abc), Bed(abc){
cout << "SoftBed(abc)" << endl;
}
}; class LeightWrightCom {
public:
LeightWrightCom() {
cout << "LeightWrightCom()" << endl;
}
LeightWrightCom(char *abc) {
cout << "LeightWrightCom(abc)" << endl;
}
}; class Type {
public:
Type() {
cout << "Type()" << endl;
}
Type(char *abc) {
cout << "Type(abc)" << endl;
}
}; class Date {
public:
Date() {
cout << "Date()" << endl;
}
Date(char *abc) {
cout << "Date(abc)" << endl;
}
}; class LeightWrightSofaBed : public SoftBed, virtual public LeightWrightCom {
Type type;
Date date;
public:
LeightWrightSofaBed() {
cout << "LeightWrightSofaBed()" << endl;
}
LeightWrightSofaBed(char *abc) : SoftBed(abc), LeightWrightCom(abc), type(abc), date(abc) {
cout << "LeightWrightSofaBed(abc)" << endl;
}
}; int main()
{ LeightWrightSofaBed l1("lll"); return ;
} /*
Furniture() //没有调用有参构造函数!!
Verication3C() //没有调用有参构造函数!!
LeightWrightCom(abc) //调用了有参构造函数
Soft(abc)
Bed(abc)
SoftBed(abc)
Type(abc)
Date(abc)
LeightWrightSofaBed(abc)
*/

C++中的继承和多继承的更多相关文章

  1. C++中的多重继承与虚继承的问题

    1.C++支持多重继承,但是一般情况下,建议使用单一继承. 类D继承自B类和C类,而B类和C类都继承自类A,因此出现下图所示情况: A          A \          / B     C ...

  2. HIbernate学习笔记(七) hibernate中的集合映射和继承映射

    九.       集合映射 1. Set 2. List a)        @OrderBy 注意:List与Set注解是一样的,就是把Set更改为List就可以了 private List< ...

  3. JS中通过call方法实现继承

    原文:JS中通过call方法实现继承 讲解都写在注释里面了,有不对的地方请拍砖,谢谢! <html xmlns="http://www.w3.org/1999/xhtml"& ...

  4. Java中的集合类型的继承关系图

    Java中的集合类型的继承关系图

  5. 盘点CSS中可以和不可以继承的属性

    CSS中可以和不可以继承的属性   一.无继承性的属性 1.display:规定元素应该生成的框的类型 2.文本属性: vertical-align:垂直文本对齐 text-decoration:规定 ...

  6. 对Java中多态,封装,继承的认识(重要)

                                                            一.Java面向对象编程有三大特性:封装,继承,多态 在了解多态之前我觉得应该先了解一下 ...

  7. oc中protocol、category和继承的区别

    OC中protocol.category和继承的区别以前还是有点迷糊,面试的时候说的有点混乱,现在结合一些资料总结一下. 利用继承,多态是一个很好的保持"对扩展开放.对更改封闭"( ...

  8. C++ 中私有继承、保护继承与公有继承

    区别 下面通过一个示例来介绍三种继承的区别. 定义一个基类(假设为一个快退休的富豪): class RichMan { public: RichMan(); ~RichMan(); int m_com ...

  9. js中的对象创建与继承

    对象创建 1.工厂模式 优点:解决了创建多个相似对象的问题 缺点:没有解决对象识别问题:每一个对象都有一套自己的函数,浪费资源 function createPerson(name, age, job ...

  10. Es5中的类和静态方法 继承

    Es5中的类和静态方法 继承(原型链继承.对象冒充继承.原型链+对象冒充组合继承) // es5里面的类 //1.最简单的类 // function Person(){ // this.name='张 ...

随机推荐

  1. 深入理解java虚拟机---java虚拟机内存管理(五)

    1.深入理解java虚拟机 总图: 1.线程共享区: 2.线程独占区: 1.程序计数器 理解为当前线程锁执行的字节码的行号指示器,程序计数器没有内存异常错误.

  2. SpringMVC 接受页面传递参数

    一共是五种传参方式: 一:直接将请求参数名作为Controller中方法的形参 public  String login (String username,String password)   : 解 ...

  3. js 唤起APP

    常常有这样的场景,咱们开发出来的APP需要进行推广,比如在页面顶部来一张大Banner图片,亦或一张二维码.但往往我们都是直接给推广图片加了一个下载链接(App Store中的).所以咱们来模拟一下用 ...

  4. Python 基础字典的增删改查

    # 字典相关的代码## 1.字典的特性:a 字典的无序性: b 数据关联性强 C 键键值对 唯一一个映射数据类型# 字典的键必修二是可哈希的(不可变的数据类型:,字符串,数字的,布尔值,元祖)# 并且 ...

  5. os与操作系统进行交互,sys解释器相关,random随机数,shutil解压和压缩

    1.os 与操作系统相关 对文件的处理 对路径的处理 import os#主要用于与操作系统进行交互 掌握: print(os.makedirs('a/b/c'))#创建目录 可用递归创建 print ...

  6. select语句的高级应用及实例

    本文介绍的select高级应用主要包括:联合查询.分组查询.嵌套查询和限定查询数目等,与实例对照演示,所使用数据库为sqlite3. 部门表(dept) CREATE TABLE dept( id I ...

  7. java学习笔记6(面向对象1:概念,private)

    1.思想: 面向过程的思想:遇到问题时想,我该如何做,然后分步骤实现: 面向对象的思想:遇到问题时想,我该派谁去做这件事,至于他怎么做,与我无关,我只要最后的结果. 实际举例:我们要组装一台电脑: 面 ...

  8. Linux 下各个目录的作用及内容

    在 Linux 下,我们看到的是文件夹(目录): 在早期的 UNIX 系统中,各个厂家各自定义了自己的 UNIX 系统文件目录,比较混乱.Linux 面世不久后,对文件目录进行了标准化,于1994年对 ...

  9. menson 使用方法

    参考:http://mesonbuild.com/Running-Meson.html#configuring-the-source https://github.com/google/googlet ...

  10. hadoop day 1

    hadoop是什么? 解决的问题: 海量数据的存储(HDFS):供hbase,mapreduce进行处理 海量数据的分析(MapReduce) 资源管理调度(YARN) 搜索引擎: 爬虫系统+站内搜索 ...