【C++基础】类和对象——继承

本文介绍了C++中的类和对象继承,包括继承的基本语法、继承方式(公共、保护、私有)、继承规则、对象模型、构造和析构函数的顺序、同名成员的处理以及多继承和菱形继承的概念与问题解决。重点讨论了虚继承如何解决菱形继承导致的二义性和冗余问题。

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

【C++基础】类和对象——继承

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

  • 继承可以有效减少重复代码。
  • 派生类会继承基类的属性
  • 基类表现共性,派生类表现个性

一、继承的基本语法

语法:class 派生类 : 权限 基类 { }

示例:
#include<iostream>
using namespace std;

//父类或称基类
class BasePage
{
public:
	void header()
	{
		cout << "首页、登录、注册(公共头部)" << endl;
	}

	void footer()
	{
		cout << "帮助中心、交流合作(公共底部)" << endl;
	}
};


//子类或称派生类
class Java : public BasePage
{
public:
	void context()
	{
		cout << "JAVA 页面" << endl;
	}

};

//子类或称派生类
class Cpp : public BasePage
{
public:
	void context()
	{
		cout << "Python 页面" << endl;
	}
};


int main()
{
	Java j;
	j.header();
	j.context();
	j.footer();

	cout << endl;

	Cpp c;
	c.header();
	c.context();
	c.footer();
}

输出:
在这里插入图片描述

二、继承方式

继承语法:class 派生类 : 权限 基类 { }

继承方式一共有三种:

  • 公共继承
  • 保护继承
  • 私有继承

继承规则:

  1. 私有属性(private):能继承,但会被隐藏,外在表现为未继承。
  2. 公共权限(public):除了私有权限的属性,其他属性原封不动的继承
  3. 保护权限(protected):除了私有权限的属性,其他属性均继承为保护权限(保护权限会覆盖公共权限)
继承规则示例:
//基类
class A
{
public:
	int a;
protected:
	int b;
private:
	int c;
};

//派生类
class B : public A
{
//继承来自A的属性
protected:
	int a;
	int b;
};

//派生类
class C : protected A
{
//继承来自A的属性
protected:
	int a;
	int b;
};

//派生类
class D : private A 
{
//继承来自A的属性
private:
	int a;
	int b;
};
示例
#include<iostream>
using namespace std;

//基类
class A
{
public:
	int a;
protected:
	int b;
private:
	int c;
};

//派生类
class B : public A
{
public:
	void function()
	{
		a;
		b;
	}
};

//派生类
class C : protected A
{
	void function()
	{
		a;
		b;
	}
};

//派生类
class D : private A 
{
	void function()
	{
		a;
		b;
	}
};


int main()
{
	//能访问到的属性如下
	B b;
	b.a;	//a为公共权限(public)

	C c;

	D d;
}

三、继承中的对象模型

派生类继承了基类哪些属性?

利用开发人员命令提示工具查看对象模型
打开vs的开发人员命令提示符
跳转文件路径 cd 项目文件夹下
查看命令 cl /dl reportSingleClassLayout类名 文件名

示例:
#include<iostream>
using namespace std;

//基类
class Base
{
public:
	int b_A;
protected:
	int b_B;
private:
	int b_C;	//被继承了,但也被隐藏了起来
};

//派生类
class Son : Base
{
public:
	int s_D;
};

class A
{
public:
	int a;
};

int main()
{
	//父类中的所有非静态成员属性都会被子类继承下去
	//父类中私有成员属性,是被编译器隐藏了,因此访问不到
	cout << "sizeof(Son) = " << sizeof(Son) << endl;
	cout << "sizeof(A) = " << sizeof(A) << endl;
}

继承中的构造和析构顺序

子类继承父类后,当创建子类对象时,也会调用父类的构造函数

递归调用

  • 基类先调用,最后释放
  • 派生类后调用,先释放

如图所示
在这里插入图片描述

示例:
#include<iostream>
using namespace std;

//基类
class Base
{
public:
	Base()
	{
		cout << "基类的 构造 函数" << endl;
	}
	~Base()
	{
		cout << "基类的 析构 函数" << endl;
	}
};

//派生类
class Son : Base
{
public:
	Son()
	{
		cout << "派生类的 构造 函数" << endl;
	}
	~Son()
	{
		cout << "派生类的 析构 函数" << endl;
	}
};

int main()
{
	Son s;
}

五、继承同名成员处理方式

基类与派生类出现同名成员时的梳理方式

  • 访问派生类同名成员 直接访问即可
  • 访问基类同名成员 需要加作用域
示例:
#include<iostream>
using namespace std;

//基类
class Base
{
public:
	int a;

	void func()
	{
		cout << "Base 的 func()" << endl;
	}
};

//派生类
class Son :public Base
{
public:
	void func()
	{
		cout << "Son 的 func()" << endl;
	}
};

int main()
{
	Son s;

	s.func();
	//加基类作用域
	s.Base::func();
}

输出:
在这里插入图片描述

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

静态成员和非静态成员出现同名,处理方式一致

  • 访问派生类同名成员 直接访问即可
  • 访问基类同名成员 需要加作用域
示例:
#include<iostream>
using namespace std;

//基类
class Base
{
public:
	int a;

	static void func()
	{
		cout << "Base 的 static func()" << endl;
	}
};

//派生类
class Son :public Base
{
public:
	static void func()
	{
		cout << "Son 的 static func()" << endl;
	}
};

int main()
{
	Son s;

	cout << "1、通过对象访问" << endl;
	s.func();
	s.Base::func();

	cout << "2、通过类名访问" << endl;
	Son::func();
	Base::func();
	//访问Son类中继承的基类成员
	Son::Base::func();
}

输出:
在这里插入图片描述

七、多继承语法

C++允许一个类继承多个类

语法:class 派生类 : 权限 基类1, 权限 基类2 ... { }

出现同名函数,使用作用域来区分

不建议使用多继承

示例:
#include<iostream>
using namespace std;

//基类1
class Base1
{
public:
	void func()
	{
		cout << "Base1 的 func()" << endl;
	}
};

//基类2
class Base2
{
public:
	void func()
	{
		cout << "Base2 的 func()" << endl;
	}
};

//派生类
class Son :public Base1, public Base2
{
public:
	void func()
	{
		cout << "Son 的 func()" << endl;
	}
};

int main()
{
	Son s;

	s.func();
	s.Base1::func();
	s.Base2::func();

}

输出:
在这里插入图片描述

八、菱形继承

菱形继承概念

  • 两个派生类继承同一个基类
  • 又有某个类同时继承这两个派生类
  • 这种继承被称为菱形继承,或者钻石继承

例如:
在这里插入图片描述

菱形继承的问题

  1. 马和驴都继承了动物的数据,当骡子使用数据时,会产生二义性
  2. 骡子实际上继承两份相同动物的属性,产生冗余。
问题示例:
#include<iostream>
using namespace std;

class Animal
{
public:
	int price;
};

class Horse:public Animal{};

class Donkey :public Animal {};

class Mule :public Horse, public Donkey {};

int main()
{
	Mule mule;

	mule.Horse::price = 10;
	mule.Donkey::price = 20;
	//菱形继承时,两个父类拥有相同数据,需要加作用域来区分
	cout << "mule.Horse::price = " << mule.Horse::price << endl;
	cout << "mule.Donkey::price = " << mule.Donkey::price << endl;
	//Mule的price属性只需要一个
}

输出:
在这里插入图片描述

使用虚继承来解决菱形继承的问题

示例:
#include<iostream>
using namespace std;

class Animal
{
public:
	int price;
};

//使用虚继承来解决菱形继承的问题
//继承之前,加上关键字 virtual 变为虚继承
//此时Animal类称为 虚继承
class Horse:virtual public Animal{};

class Donkey :virtual public Animal {};

class Mule :public Horse, public Donkey {};

int main()
{
	Mule mule;

	mule.price = 10;
	
	cout << "mule.price = " << mule.price << endl;
	cout << "sizeof(mule) = " << sizeof(mule) << endl;
}

输出:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值