C++继承:

本文详细介绍了C++中的继承概念,包括继承的基本语法、继承方式(公共继承、保护继承、私有继承)、继承中的对象模型、构造和析构的顺序、同名成员的处理方式以及静态成员的处理。此外,还探讨了多继承和菱形继承问题,以及如何利用虚继承解决菱形继承带来的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继承是面向对象三大特性之一

有些类与类之间存在特殊关系:例如:
动物——(猫、狗…)———(加菲猫、波斯猫…哈士奇、京巴…)

下级别的成员除了拥有上一级的共性,还有自己的特性;
这时,我们就可以考虑利用继承的技术,减少重复代码;

继承的基本语法:

例如:好比我们平时看到的很多网站中,有公共的头部、公共的地步;而其他子页面只有重心内容不同;
这时就可以利用普通写法和继承的写法来实现网页中的内容;
继承的好处:减少重复代码;
语法:class 子类 :继承方式 父类{ }
子类 也称为 派生类;
父类 也称为 基类;

  • 例如:
    定义一个父类:
class BasePage{
	public:
	   void header(){}
	   void footer(){}
	   void left(){}
}

语法:
class A :public B;
A类称为子类 或 派生类;
B类称为父类 或 基类;

定义Java页面、C++页面:

class Java : public BasePage{
	public :
	  void content(){ cout<<"JAVA";}
}
class C++ : public BasePage{
	publicvoid content(){ cout << "c++"; }
}

派生类中的成员,包含两大部分:
一类是从基类继承过来的,一类是自己增加的成员;
从基类继承过来的表现其共性,而新增的成员体现其个性;

继承方式

继承的语法:class 子类 :继承方式 父类
继承方式一共有三种:

  • 公共继承–public
  • 保护继承–protected
  • 私有继承–private
    在这里插入图片描述

注意:
无论是public共有继承,protected保护继承,还是private私有继承都不可以访问父类的私有属性;

公有继承:

  • 父类中的公共权限成员,到子类中依然是公共权限;
  • 父类中的保护权限成员,到子类中依然是保护权限;
  • 父类中的私有权限成员,子类访问不到;
    在这里插入图片描述

回顾三大权限的用法:

  • 类在设计时,可以把属性和行为放在不同的权限下,加一控制;
    访问权限有3种:
    1.public——公共权限:类内可以访问,类外也可以访问
    2.protected——保护权限:类内可以访问,类外不可以访问
    3.private——私有权限:类内可以访问,类外不可以访问

**保护权限与私有权限的区别:
保护权限:protected:儿子可以访问父亲中的保护内容
私有权限:private儿子不可以访问父亲的私有内容;**

保护继承:

  • 父类中的公共权限和保护权限到子类中都转为保护权限;
  • 父类中的私有权限,子类访问不到;
    在这里插入图片描述
    · 所以保护继承继承到的除私有属性外都为保护权限,类外无法访问;**
    私有继承:
  • 父类中的所有非静态成员到子类中变为私有成员;
  • 所以私有继承继承到的父类成员在类外都访问不到;

继承中的对象模型:

  • 父类中的所有非静态成员属性都会被子类继承下去;
  • 父类中的私有成员属性 是被编译器给隐藏了,因此访问不到,但确实被继承下去了;

继承中构造和析构的顺序

  • 子类继承父类后,当创建子类对象时,同时也会调用父类的构造函数(即先有父类);

问题:父类和子类的构造和析构顺序是谁先谁后?
继承中的构造和析构顺序如下:
1.先构造父类,再构造子类;(即先有父类再有子类,先调用base的构造,再调用son的构造)
2.析构的顺序与构造的顺序相反;(即先调用son的析构,再调用base的析构)

继承同名成员处理方式:

  • 问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?
    1.访问子类同名成员,直接访问即可;
    2.访问父类同名成员,需要加作用域;
class Base {
public:
	Base() {
		m_A = 100;
	}
	int m_A;
};
class Son :public Base {
public:
	Son() {
		m_A = 200;
	}
	int m_A;
};
int main() {
	Son s;
	cout << "Son下的 m_A=" << s.m_A << endl;
如果通过子类对象  访问到父类中同名成员,需要加作用域;
	cout << "Base下的 m_A=" << s.Base::m_A << endl;
	system("pause");
	return 0;
}
  • 同名函数:正常情况下(与同名成员变量一样)
class Base {
public:
	void func() {
		cout << "Base下的func" << endl;
	}
	void func(int a) {
		cout << a<<endl;
	}
};
class Son :public Base {
public:
	void func() {
		cout << "son下的func" << endl;
	}
};

int main() {

	Son s;
正常使用下同名成员变量一样
	s.func();
	s.Base::func();
当出现同名函数重载时:
如果子类中出现和同名的成员函数,子类的同名成员会隐藏掉父类中所有父类中所有同名成员函数;
如果想访问到父类中被隐藏的同名成员函数,需要加作用域;
	//s.func(100);————不可使用,因为子类中没有有参数的func()函数
	s.Base::func(100);

	system("pause");
	return 0;
}

补加:
3.当子类中出现和同名的成员函数,子类的同名成员会隐藏掉父类中所有父类中所有同名成员函数,加作用域可以访问到父类中同名函数;

继承同名静态成员处理方式:

  • 问题:机场中同名的静态成员在子类对象上如何进行访问?
    静态成员和非静态成员出现同名,处理方式一致
    1.访问子类同名成员,直接访问即可;
    2.访问父类同名成员,需要加作用域;

    补充——静态成员变量可以通过类名方式进行访问:
    即有两种访问方式:通过对象和通过类名;
cout<<"Son::m_A"<<Son::m_A;
cout<<"Son::m_A"<<Son::Base::m_A;

另外:子类出现和父类同名静态成员函数,也会隐藏父类中所有同名成员函数;
如果想访问父类中杯隐藏同名成员,需要加作用域:

Son::Base::func(100);

回顾静态变量:

  • 静态成员就是在成员变量和成员函数前加上关键字static,称之为静态成员;
    静态成员分为静态成员变量和静态成员函数;

静态成员变量:

  • 所有对象共享同一份数据;
  • 在编译阶段分配内存;
  • 类内声明,类外初始化;
class Base{
	//静态成员变量
	static int m_A;
}
//静态成员变量是在类内声明,类外初始化
int Person::m_A = 0;

注意:类外初始化的时候一定要加上作用域,不然无法初始化;

静态成员函数不可以访问非静态成员变量
因为非静态成员变量会指定为那个对象的属性值,所以直接使用不知道是那个对象的属性值
而静态成员函数为公用,且静态成员变量为也为所有对象共享同一份数据;
所以静态成员函数只能访问静态成员变量

多继承语法

C++允许一个类继承多个类;
语法: class 子类 :继承方式 父类1,继承方式 父类2{ }

多继承中可能会引发父类中有同名成员出现,需要加作用域区分;所以C++实际开发中不建议用多机场;

菱形继承:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义;
所以需要利用虚继承来解决菱形继承问题

.在这里插入图片描述

利用虚继承 解决菱形继承的问题;
继承之前 加上关键字 virtual 变为虚继承
Animal类称为 虚基类

在这里插入图片描述
利用对象模型进行查看:
虚继承相当于运用指针(或引用的方法),所以继承的子类使用虚继承则是只在一块内存上进行操作;

vbptr :
v——virtual (英 /ˈvɜːtʃuəl/ )虚的,虚拟的;
b——base
ptr——pointer;( /ˈpɔɪntə®/ 指针)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值