c++中的类继承

news2024/11/28 12:53:49

面向对象编程的主要目的是之一是提供可重用的代码。开发新项目,尤其是当项目十分庞大时,重用经过测试的代码比重新编写代码要好得多。使用已有的代码可以节省时间,由于已有的代码已被使用和测试过,因此有助于避免在程序中引入错误。另外,必须考虑的细节越少,便越能专注于程序的整体策略。

c++类提供了更高层次的重用性。目前,很多厂商提供了类库,类库由类声明和实现构成。因为类组合了数据表示和类方法,因此提供了比函数库更加完整的程序包。通常,类库是以源代码的方式提供的,这意味这可以对其进行修改,以满足需求。然而,c++提供了比修改代码更好的方法来扩展和修改类。这种方法叫做类继承,它能够从已有的类派生出新的类,而派生类继承了原有类(基类)的特征,包括方法。通过继承派生出的类通常比设计新类要容易得多。

可以通过继承完成的一些工作

1、可以在已有类的基础上添加功能。

2、可以给类添加数据。

3、可以修改类方法的行为。

可以通过复制原始类代码,并对其进行修改来完成上述工作,但继承机制只需提供新特性,甚至不需要访问源代码就可以诞生出类。

1、类的继承

概念:新的类(子类)从已知的类(父类)中得到已有的特征的过程

从一个类派生出另一个类时,原始类称为基类(也叫父类),继承类称为派生类(子类)。

作用:继承可以减少重复的代码,比如弗雷已经提供的方法,子类可以直接使用,不必再去实现

继承的格式(单继承)

class 子类名:继承方式 父类(继承方式省略默认是私有继承)

{

        子类成员

};

1.1派生一个类

派生类对象具有以下特征:

1、派生类对象存储了基类的数据成员(派生类继承了基类的实现)

2、派生类对象可以使用基的方法(派生类继承了基类的接口)

需要在继承特性中添加什么呢?

1、派生类需要自己的构造函数(构造函数必须给新成员和继承的成员提供数据)

2、派生类可以根据需要添加额外的数据成员和成员函数

1.2构造函数:访问权限的考虑

派生类不能直接访问基类的私有成员,而必须通过基类方法进行访问

创建派生类对象时,程序首先创建基类对象。从概念上说,这意味这基类对象应当在程序进入派生类构造函数之前被创建。c++使用成员初始化列表语法来完成这种工作。必须首先创建基类对象,如果不调用基类构造函数,程序将使用默认的基类构造函数。除非要使用默认构造函数,否则应显式调用正确的构造函数。

有关派生类构造函数的要求如下:

1、首先创建基类对象

2、派生类构造函数应通过成员初始化列表将基类信息传递给基类构造函数

3、派生类构造函数应初始化派生类新增的数据成员

释放对象的顺序与创建对象的顺序相反,即首先执行派生类的析构函数,然后自动调用基类的析构函数。

注意:创建派生类对象是,程序首先调用基类构造函数,然后再调用派生类构造函数。基类构造函数负责初始化继承的数据成员,派生类构造函数主要用于初始化新增的数据成员。派生类的构造函数总是调用一个基类构造函数。可以使用初始化器语法指明要使用的基类构造函数,否则将使用默认的基类构造函数。派生类对象过期式,程序将使用用派生类析构函数。然后再调用基类析构函数。

成员初始化列表

派生类构造函数可以使用初始化器列表机制值传递给基类构造函数

子类::子类(数据类型):基类(数据类型){        ...        }

如果没有在成员初始化列表中提供基类构造函数,程序将使用默认的基类构造函数。成员初始化列表只能用于构造函数。

#include <iostream>
#include<cstring>
using namespace std;

//基类-->父类
class Base
{
public:
    Base(){cout << "Base()" << endl;}
    ~Base(){cout << "~Base()" << endl;}

    void setA(int n)
    {
        a = n;
    }

    int getA()
    {
        return a;
    }

    void show(int a,int b)
    {
        cout<<a<<" "<<b<<endl;
    }
private:
    int a;
};

//派生类-->子类
class Child:public Base //继承方式省略默认是私有继承
{
public:
    Child(){cout << "Child()" << endl;}
    ~Child(){cout << "~Child()" << endl;}

    // void show(int a,int b) //基类里面有这种方法,那么子类里面可以不用重复实现
    // {
    //     cout<<a<<" "<<b<<endl;
    // }   
private:
    int b;
};

int main()
{
    //实例化一个子类的对象
    Child c1;

    //通过子类的对象来调用父类的方法
    c1.setA(100);
    cout<<c1.getA()<<endl;

    c1.show(10,20);
    return 0;
}

1.3继承的对象模型

问题提出:从父类继承过来的成员,哪些属于子类对象中?

利用Visual studio这个编程软件下自带的开发人员命令提示符来进行查看

使用步骤:

1、打开工具窗口

2、定位到当前cpp文件的盘符

3、c1 /d1 reportSingleClassLayout查看的类名 所属文件(TAB键补全)

结论:父类中私有成员也是被子类的继承下去了,只是由编译器给隐藏后访问不到

1.4继承同名成员处理方式

当子类和父类出现同名的成员,如何通过子类的对象,访问到子类或父类中同名的数据

1、访问子类同名成员 直接访问即可

2、访问父类同名成员 需要加作用域

#include <iostream>
using namespace std;

class Base {
public:
	Base()
	{
		m_A = 100;
	}

	void func()
	{
		cout << "Base - func()调用" << endl;
	}

	void func(int a)
	{
		cout << "Base - func(int a)调用" << endl;
	}

public:
	int m_A;
};


class Son : public Base {
public:
	Son()
	{
		m_A = 200;
	}

	//当子类与父类拥有同名的成员函数,子类会隐藏父类中所有版本的同名成员函数
	//如果想访问父类中被隐藏的同名成员函数,需要加父类的作用域
	void func()
	{
		cout << "Son - func()调用" << endl;
	}
public:
	int m_A;
};

void test01()
{
	Son s;

	cout << "Son下的m_A = " << s.m_A << endl;
	cout << "Base下的m_A = " << s.Base::m_A << endl;

	s.func();
	s.Base::func();
	s.Base::func(10);

}
int main() {

	test01();

	return 0;
}

总结:

1. 子类对象可以直接访问到子类中同名成员

2. 子类对象加作用域可以访问到父类同名成员

3. 当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数

问题:继承中同名的静态成员在子类对象上如何进行访问?

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

- 访问子类同名成员   直接访问即可

- 访问父类同名成员   需要加作用域

同名静态成员处理方式和非静态处理方式一样,只不过有两种访问的方式(通过对象 和 通过类名)

2、类的多种继承方式

继承方式有三种:公有继承(public),私有继承(private),保护继承(protected)

父类成员权限/继承方式

公有继承(public)

保护继承(protected)

私有继承(private)

public

可用/public

可用/protected

可用/private

protected

可用/protected

可以/protected

可用/private

private

可以继承,但是不能直接访问,可以通过基类的公有方法和保护方法

可以继承,但是不能直接访问,可以通过基类的公有方法和保护方法

可以继承,但是不能直接访问,可以通过基类的公有方法和保护方法

上面表格权限是基类中的成员继承到子类后的成员权限

如果派生类在继承基类的时候选择公有继承(public)

那么基类的公有成员就是在派生类中也是充当公有成员,可以直接在派生类的内部和外部使用

那么基类的保护成员就是在派生类中也是充当保护成员,可以在派生类的内部使用,但是不能外部使用

那么基类的私有成员可以继承,但是不能直接访问,可以通过基类的公有方法和保护方法间接访问

如果派生类在继承基类的时候选择保护继承(protected)

那么基类的公有成员就是在派生类中是充当保护成员,可以在派生类的内部使用,但是不能外部使用

那么基类的保护成员就是在派生类中是充当保护成员,可以在派生类的内部使用,但是不能外部使用

那么基类的私有成员可以继承,但是不能直接访问,可以通过基类的公有方法和保护方法间接访问

如果派生类在继承基类的时候选择私有继承(private)

那么基类的公有成员就是在派生类中是充当私有成员,可以在派生类的内部使用,但是不能外部使用

那么基类的保护成员就是在派生类中是充当私有成员,可以在派生类的内部使用,但是不能外部使用

那么基类的私有成员可以继承,但是不能直接访问,可以通过基类的公有方法和保护方法间接访问

class Base1
{
public: 
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

//公共继承
class Son1 :public Base1
{
public:
	void func()
	{
		m_A; //可访问 public权限
		m_B; //可访问 protected权限
		//m_C; //不可访问
	}
};

void myClass()
{
	Son1 s1;
	s1.m_A; //其他类只能访问到公共权限
}

//保护继承
class Base2
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};
class Son2:protected Base2
{
public:
	void func()
	{
		m_A; //可访问 protected权限
		m_B; //可访问 protected权限
		//m_C; //不可访问
	}
};
void myClass2()
{
	Son2 s;
	//s.m_A; //不可访问
}

//私有继承
class Base3
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};
class Son3:private Base3
{
public:
	void func()
	{
		m_A; //可访问 private权限
		m_B; //可访问 private权限
		//m_C; //不可访问
	}
};
class GrandSon3 :public Son3
{
public:
	void func()
	{
		//Son3是私有继承,所以继承Son3的属性在GrandSon3中都无法访问到
		//m_A;
		//m_B;
		//m_C;
	}
}

3、类的多继承

多继承的格式

class 子类:继承方式 基类1,继承方式 基类2

{

        变量成员;

        函数成员;

};

多继承的时候,创建子类对象构造函数执行的顺序,跟基类继承的先后顺序有关

在派生类的构造函数初始化列表中指定基类的构造函数

多重继承可能给程序员带来很多新问题:

1、从两个不同的基类继承同名方法

2、从两个或更多相关基类那里继承同一个类的多个实例

所以,C++实际开发中不建议用多继承。

第一个问题可以通过子类重新实现或通过父类类名显示调用解决,我们着重于第二个问题的解决,这个问题引出一个很重要的继承:菱状继承(环状继承)

3.1菱形继承(环状继承,钻石继承)

概念:两个派生类继承同一个基类,又有某个类同时继承这两个派生类,这种继承被称为菱形继承

#include <iostream>

using namespace std;

//动物类
class Animal{
public:
    Animal(){
        cout<<"Animal()"<<endl;
    }
    Animal(int a):dataD(a)
    {
        cout<<"Animal(int a)"<<endl;
    }
    ~Animal(){
        cout<<"~Animal()"<<endl;
    }
    
    int dataD;
};


//羊类 --继承于 动物类
class Sheep:public Animal{
public:
    Sheep(){
        cout<<"Sheep()"<<endl;
    }
    Sheep(int a):dataA(a)
    {
        cout<<"Sheep(int a)"<<endl;
    }
    ~Sheep(){
        cout<<"~Sheep()"<<endl;
    }
    void show(){
         cout<<"dataA value:"<<dataA<<"\t addr:"<<&dataA<<endl;
        //cout<<"dataD value:"<<dataD<<"\t addr:"<<&dataD<<endl;
     }
    int dataA;
};


//驼类
class Tuo:public Animal{
public:
    Tuo(){
        cout<<"Tuo()"<<endl;
    }
    Tuo(int a):dataB(a)
    {
        cout<<"Tuo(int a)"<<endl;
    }
    ~Tuo(){
        cout<<"~Tuo()"<<endl;
    }
    void show(){
        cout<<"dataB value:"<<dataB<<"\t addr:"<<&dataB<<endl;
     }
    int dataB;
};

//羊驼类
//多继承 的时候 基类的构造函数执行的顺序 跟  继承的先后顺序有关
// class SheepTuo:public Tuo,public Sheep
class SheepTuo:public Sheep,public Tuo
{
public:
    //在构造函数的参数列表中指定基类的构造函数
    SheepTuo(int a,int b):Tuo(b),Sheep(a)
    {
        cout<<"SheepTuo()"<<endl;
    }
    ~SheepTuo(){
        cout<<"~SheepTuo()"<<endl;
    }
    //在子类中重写 基类的同名函数,那么基类中的同名函数就会自动隐藏
    void show(){
        cout<<"dataA value:"<<dataA<<"\t addr:"<<&dataA<<endl;
        cout<<"dataB value:"<<dataB<<"\t addr:"<<&dataB<<endl;
        cout<<"dataC value:"<<dataC<<"\t addr:"<<&dataC<<endl;
    //    cout<<"dataD value:"<<dataC<<"\t addr:"<<&dataD<<endl;
    }
    int dataC;
};


int main()
{
    //派生类对象的实例化
    SheepTuo mya(10,20);

    cout<<"mya size:"<<sizeof(mya)<<"\tmya addr:"<<&mya<<endl;

    // mya.show();
    //发生二义性问题
    //mya.Animal::dataD = 100; //错误:羊驼类里面不能直接访问动物类里面的成员
    // 通过基类的类名显示调用
    mya.Sheep::show(); //在羊驼里面可以通过羊类或者驼类的公有方法来访问动物类的成员
    // mya.Tuo::show();

    return 0;
}

3.2菱形继承的解决方法-----虚继承

概念:为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类,这时从不同的路 径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。这样不仅就解决了二义性问题,也解决了内存,避免了数据不一致的问题

虚继承格式:

class 子类名称:virtual  继承方式关键字 父类名 { };

在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧跟其后的基类起作用

#include <iostream>
using namespace std;

class Animal
{
public:
	int m_Age;
};

//继承前加virtual关键字后,变为虚继承
//此时公共的父类Animal称为虚基类
class Sheep : virtual public Animal {};
class Tuo   : virtual public Animal {};
class SheepTuo : public Sheep, public Tuo {};

void test01()
{
	SheepTuo st;
	st.Sheep::m_Age = 100;
	st.Tuo::m_Age = 200;

	cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;
	cout << "st.Tuo::m_Age = " <<  st.Tuo::m_Age << endl;
	cout << "st.m_Age = " << st.m_Age << endl;
}


int main() {

	test01();
    
	return 0;
}

vbptr详细解释

v --- virtual --- 虚拟的

b --- base   --- 基类

ptr --- pointer --- 指针

vbptr --- 虚基类指针,指向vbtable,记录相应的偏移量,指向唯一的数据内存存放位置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/423254.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Github中77k星的王炸AutoGPT,会独立思考,直接释放双手

文章目录1 前言1.1 什么是AutoGPT1.2 为什么是AutoGPT2 AutoGPT部分实例2.1 类似一个Workflow2.2 市场调研2.3 自己写播客2.4 接入客服3 安装和使用AutoGPT3.1 安装3.2 基础用法3.3 配置OpenAI的API3.4 配置谷歌API3.5 配置Pinecone API4.讨论1 前言 迄今为止&#xff0c;Gith…

枚举类注解

一、枚举类&#xff1a; 1.枚举类的使用 类的对象只有有限个&#xff0c;确定的。比如&#xff1a;星期、性别、季节 当需要定义一组常量时&#xff0c;强烈建议使用枚举类。 定义枚举类的方法&#xff1a; 一&#xff1a;jdk5.0之前&#xff0c;自定义枚举类 package com.ypl…

https访问fastdfs图片

引用&#xff1a;https://blog.csdn.net/love8753/article/details/128872320 配置nginx 的SSL模块&#xff1a;https://www.cnblogs.com/ghjbk/p/6744131.html 获取ssl证书 将ssl证书&#xff0c;拷贝到服务器的一个目录下 nginx添加 http_ssl_module 最开始安装的nginx只有 …

Spimes x5.0主题模板全开源源码/Typecho主题模板

☑️ 品牌&#xff1a;Typecho ☑️ 语言&#xff1a;PHP ☑️ 类型&#xff1a;主题模板 ☑️ 支持&#xff1a;PCWAP &#x1f389;有需要的朋友记得关赞评&#xff0c;底部分享获取&#xff01;&#xff01;&#xff01; &#x1f389; ✨ 源码介绍 Spimes x5.0主题模板全开…

【2023 年第十三届 MathorCup 高校数学建模挑战赛】 B 题 城市轨道交通列车时刻表优化问题 详细建模方案及代码实现

2023-4-15 更新了代码 【2023 年第十三届 MathorCup 高校数学建模挑战赛】 B 题 城市轨道交通列车时刻表优化问题 更新信息&#xff1a;2023-4-15 更新了代码 1 题目 列车时刻表优化问题是轨道交通领域行车组织方式的经典问题之一。 列车时刻表规定了列车在每个车站的到达和…

让手机、电视都用上Windows,微软开起了网吧

二十多年前 Windows 95 开启了家用 PC 时代。 Win XP 、Win7 … 一代代经典系统的诞生&#xff0c;Windows的市场份额彻底实现一家独大。 不过随着移动设备的兴起&#xff0c;Windows 的地位显然不如从前。 苹果、Google 都在多平台发力&#xff0c;而微软 Windows Phone 的试…

安全信息和事件管理 (SIEM)工具

组织的 IT 基础架构每天都会生成大量日志数据。这些日志包含重要信息&#xff0c;可提供有关用户行为、网络异常、系统停机、策略违规、内部威胁、法规遵从性等的见解和网络安全情报。 但是&#xff0c;在没有自动日志分析器工具的情况下手动分析这些事件日志和系统日志的任务…

2023年4月中国数据库排行榜:达梦厚积薄发夺探花,亚信、星环勇毅笃行有突破

青山遮不住&#xff0c;毕竟东流去。 生机勃勃的春天送来了2023年4月的 墨天轮中国数据库流行度排行。 本月共有263个数据库参与排名&#xff0c;排行榜前30的数据库中&#xff0c;有13个数据库崭露头角&#xff0c;处于上行趋势&#xff0c;中国数据库行业整体流行度有所增加。…

在云服务器上搭建Tomcat

这里&#xff0c;我使用的是putty和winscp。 具体步骤&#xff1a; 以下是在云服务器上搭建Tomcat的步骤&#xff1a; 1. 在本地电脑上打开winscp&#xff0c;连接到云服务器。将Tomcat程序包上传到服务器上。 2. 登录服务器&#xff0c;在终端中输入以下命令&#xff0c;解…

Nginx概述与配置

一、Nginx概述 1、Nginx的特点 一款高性能、轻量级web服务 • 稳定性高 • 系统资源消耗低高 • 对HTTP并发连接的处理能力 单台物理服务器可支持30000~50000个并发请求 2、 Nginx编译安装 • 安装支持软件 • 创建运行用户、组 • 编译安装Nginx 3、Nginx运行控制 …

mmaction行为识别模型数据集训练

参考文献 https://mmaction2.readthedocs.io/en/latest/supported_datasets.html **MMAction2 支持两种类型的数据格式&#xff1a;帧的格式和视频。**前者广泛应用于TSN等之前的项目中。当 SSD 可用时很快&#xff0c;但无法扩展到快速增长的数据集时。&#xff08;例如&#…

ESP8266 +I2C SSD1306 OLED仿数码管时钟

ESP8266 +I2C SSD1306 OLED仿数码管时钟 📌相关篇《ESP8266 + STC15+ I2C OLED带网络校时功能的定时器时钟》🎬显示效果:🔖本工程基于Arduino IDE框架下开发。🌿采用esp8266:Nodemcu📑功能组成部分 🌿屏幕驱动显示🌿时间获取🌿自定义字体📓屏幕驱动显示 🍁…

Hadoop Partition函数应用(归档)

一、实例描述 在这个实例里我们使用简单的数据集&#xff0c;里面包含多条数据&#xff0c;每条数据由姓名、年龄、性别和成绩组成。实例要求是按照如下规则归档用户。 1.找出年龄小于20岁中男生和女生的最大分数   2.找出20岁到50岁男生和女生的最大分数   3.找出50岁以上…

神器集合!这12个免费工具可以让您的工作更高效

好的工具&#xff0c;能够帮助我们更高效地完成工作&#xff0c;节省时间和精力; 节省出更多的摸鱼时间&#xff01; 本文将介绍 12 款绝佳的免费效率工具&#xff0c;这些工具可以让你事半功倍&#xff0c;提高工作效率。无论你是一名程序员、设计师、学生还是白领&#xff0c…

微观世界的详细地图:微生物生态位

是什么定义了微生物的栖息地 - 生态位&#xff1f;它是温度、湿度和营养成分等环境因素的组合。很难预测每一个因素的确切贡献度。Bas E. Dutilh研究组 基于生活在一起的微生物群体&#xff0c;重新定义了微生物生态位。无论是在温泉、人体肠道还是深海中&#xff0c;微生物几乎…

助力工业物联网,工业大数据之ODS层构建:需求分析【八】

文章目录01&#xff1a;ODS层构建&#xff1a;需求分析02&#xff1a;ODS层构建&#xff1a;创建项目环境03&#xff1a;ODS层构建&#xff1a;代码导入01&#xff1a;ODS层构建&#xff1a;需求分析 目标&#xff1a;掌握ODS层构建的实现需求 路径 step1&#xff1a;目标step…

二甲医院云his系统源码,已在多家医院全面实际使用,系统稳定可靠

云his系统源码&#xff0c;基于云计算技术的B/S架构的HIS系统源码 文末获取联系&#xff01; 基于云计算技术的B/S架构的HIS系统&#xff0c;为基层医疗机构提供标准化的、信息化的、可共享的医疗信息管理系统&#xff0c;实现医患事务管理和临床诊疗管理等标准医疗管理信息系统…

HTML中的图片标签,真的如你认为的那么简单吗?

今天讨论一个很有意思的话题&#xff1a; HTML 中的图片真的那么简单吗&#xff1f; HTML 中的图片 <img>&#xff1a;图像嵌入元素 MDN Web Docs 地址&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/img 在一开始时&#xff0c;Web 仅有文…

摄影知识整理

目录 焦距 焦距分类 对焦 相机的MF与AF 自动对焦操作 自动对焦方式 镜头防抖 防抖模式 景深 景深的作用 影响景深的因素 景深预览 摄影三大元素 光圈 光圈的作用 光圈与景深的关系 感光度&#xff08;ISO) 注意 感光度的作用 快门 B门与T门 快门速度 闪…

软件工程环境(Maven)—javaEE

文章目录1.如何使用Maven1.1创建一个Maven项目&#xff08;项目使用Maven来进行构建&#xff09;1.2设置项目的信息1.3配置Maven项目&#xff08;在项目路径下pom.xml&#xff0c;Maven配置文件&#xff09;1.4验证配置成功2.Maven的使用2.1观察开发项目结构2.2xml文件2.3Maven…