第六层:继承(下)

简介: 第六层:继承(下)

静态成员


静态成员的访问有两种:


1.通过对象访问

2.通过类名访问

对于这两个方法,第一种与非静态成员是一样的,可以验证一下第二种——通过类名访问:


#include<iostream>
using namespace std;
class A
{
public:
  static void a()
  {
  cout << "父类中调用" << endl;
  }
};
class A1:public A
{
public:
  static void a()
  {
  cout << "子类中调用" << endl;
  }
};
void test1()
{
  A1 a1;
  A1::a();
  A1::A::a();
}
int main()
{
  test1();
  return 0;
}


0a2653c851af460fa595bd959398a8f1.png

静态函数发生函数重载时也与非静态函数发生函数重载一样。


多继承


在C++种,允许一个类继承多个类,这个时候就是多继承


语法


class 子类: 继承方式 父类1 , 继承方式 父类2 …


注意


在多继承中,多个父类中可能有同名成员出现,这个时候需要加作用域来区分


多继承中的对象模型


那当子类继承多个父类的时候,每个父类内的非静态成员都会被继承过去吗?通过代码验证一下:


#include<iostream>
using namespace std;
class A
{
public:
  int a;
  int b;
};
class A1
{
public:
  int _a;
  int _b;
};
class AA :public A, public A1
{
public:
  int _a1;
  int _b1;
};
void test1()
{
  AA aa;
  cout << sizeof(aa) << endl;
}
int main()
{
  test1();
  return 0;
}


0a2653c851af460fa595bd959398a8f1.png

和普通继承一样,每个父类的非静态成员都会被继承到子类当中。


多继承父类成员名相同


假设现在两个父类,有两个成员名时一样的,那子类能直接访问这个成员吗?

#include<iostream>
using namespace std;
class A
{
public:
  int _a;
  int b;
};
class A1
{
public:
  int _a;
  int _b;
};
class AA :public A, public A1
{
public:
  int _a1;
  int _b1;
};
void test1()
{
  AA aa;
  aa._a;
}
int main()
{
  test1();
  return 0;
}


0eacb84100b54626af849e6b562bf92a.png

0eacb84100b54626af849e6b562bf92a.png

编译器是直接报错的,是因为编译器不知道这个成员是来自与哪个父类,这个情况在C++中有个专业名词,叫做二义性,这个时候要怎么样才能访问到呢?就需要进行加作用域,假设现在访问A内的_a:


#include<iostream>
using namespace std;
class A
{
public:
  int _a;
  int b;
};
class A1
{
public:
  int _a;
  int _b;
};
class AA :public A, public A1
{
public:
  int _a1;
  int _b1;
};
void test1()
{
  AA aa;
  aa.A::_a = 10;
  cout<<aa.A::_a<<endl;
}
int main()
{
  test1();
  return 0;
}

2d65d23f6d4748949b924e4057485923.png


菱形继承


概念


两个子类继承了同一个父类,又有一个类,同时继承了两个子类


0a2653c851af460fa595bd959398a8f1.png


菱形继承出现的问题


马和驴都继承了动物的数据,在骡子使用数据的时候,就会产生二义性,骡子继承动物的数据只需要一份,那应该怎么办?

虚继承

对于上面所说的二义性的问题,因为同样的数据只需要一份,这个时候就可以在继承的时候加上关键字:


vritual

将继承变成虚继承,这个时候最大的父类就为虚基类,可以用代码试验:


#include<iostream>
using namespace std;
class A
{
public:
  int a;
  int b;
};
class AA:virtual public A
{
};
class AA1:virtual public A
{
};
class AAA :public AA, public AA1
{
};
void test1()
{
  AAA a;
  a.AA::a = 10;
  a.AA1::a = 20;
  cout << a.AA::a << endl;
  cout << a.AA1::a << endl;
}
int main()
{
  test1();
  return 0;
}

0eacb84100b54626af849e6b562bf92a.png

发现,两个数据修改输出的结果是一样的,这个时候就是虚继承起到的作用,让将内部数据共享了一个,这个时候最小的子类也可以直接访问到这个属性:


#include<iostream>
using namespace std;
class A
{
public:
  int a;
  int b;
};
class AA:virtual public A
{
};
class AA1:virtual public A
{
};
class AAA :public AA, public AA1
{
};
void test1()
{
  AAA a;
  a.AA::a = 10;
  a.AA1::a = 20;
  cout << a.a << endl;
}
int main()
{
  test1();
  return 0;
}

2d65d23f6d4748949b924e4057485923.png

这是为什么呢?那这个时候从父类继承下来些什么?这个时候从父类继承下来一个指针:


vbptr

这个指针叫做虚基类指针,它会指向一个叫做:


vbtable

虚基类表,虚基类表中有一个偏移量,这个偏移量会指向一个数据,每个子类指向的数据都是同一份,这个时候数据就只会有一个。

2e9b90b2ca334476abebe75bafe6eeaa.png


步入第七层


石碑倒下,大片尘土飞扬,尘土散去,只留下一串脚印,通往第七层…


本章知识点(图片形式)


4cebaac233b3433da32a72337a77fc60.png


😘预知后事如何,关注新专栏,和我一起征服C++这座巨塔

🚀专栏:C++爬塔日记

🙉都看到这里了,留下你们的👍点赞+⭐收藏+📋评论吧🙉


相关文章
|
人工智能 移动开发 小程序
【Java】医院智能导诊小程序源码,springboot框架
【Java】医院智能导诊小程序源码,springboot框架
315 0
|
9月前
|
传感器 人工智能 数据可视化
打造农业大数据平台,助力农业现代化高质量发展!
中安数码积极响应农业农村部《全国智慧农业行动计划(2024—2028年)》,推出智慧农业大数据平台解决方案。该方案涵盖驾驶舱、农业用地“一张图”、土壤环境监测、土地质量评价、作物生长状态监测评估及农业生产管理等功能模块,通过大数据、AI、GIS等技术实现农业智能化、精准化发展,助力提升农业生产效率与资源利用率,推动现代农业高质量发展。
Sublime Text3安装插件报错:There are no packages available for installation
Sublime Text3安装插件报错:There are no packages available for installation
299 0
|
运维 监控 安全
|
存储 安全 Unix
22 Cookie
路老师在知乎上分享PHP语言的知识,帮助大家入门并深入了解PHP。本文主要介绍Cookie的概念、功能及管理方法,包括如何创建、读取、删除Cookie,以及Cookie的生命周期等内容。纯干货,技术知识分享。
219 0
|
SQL 安全 关系型数据库
MySQL数据库——事务-简介、事务操作、四大特性、并发事务问题、事务隔离级别
MySQL数据库——事务-简介、事务操作、四大特性、并发事务问题、事务隔离级别
305 1
|
消息中间件 运维 监控
全套完整版实战型Java云HIS系统源码
全套完整版实战型Java云HIS系统源码
574 1
|
设计模式 运维 分布式计算
工作经验小结(2023.11.21)
工作经验小结(2023.11.21)
328 1
|
API
FreeRTOS学习笔记—任务挂起和恢复
本文学习了FreeRTOS任务挂起和解挂的内容。编程实现了任务挂起和解挂。对于编程实现中的问题进行了分析总结。
491 0
FreeRTOS学习笔记—任务挂起和恢复
|
SQL 数据采集 分布式计算
Spark SQL中的聚合与窗口函数
Spark SQL中的聚合与窗口函数