C++:继承性

一、基本概念

  • 一个基类可以派生多个派生类,一个派生类也可以由多个基类派生而成
  • 继承
    • 单一继承
    • 多重继承
  • 继承方式(缺省默认:private)
    • public
    • private
    • protected

公有继承

保护继承

私有继承

公有成员

publicprotectedprivate
保护成员protectedprotectedprivate
私有成员不可见不可见不可见
  • 基类的 private 成员不可以被继承

二、派生类的构造及析构

#include <iostream>
using namespace std;

class a1
{
public:
    a1()
    {
        cout << "a1 Constructor called" << endl;
    }
    ~a1()
    {
        cout << "a1 Destructor called" << endl;
    }
};

class a2
{
public:
    a2()
    {
        cout << "a2 Constructor called" << endl;
    }
    ~a2()
    {
        cout << "a2 Destructor called" << endl;
    }
};

class Derived : public a1, public a2
{
public:
    Derived()
    {
        cout << "Derived Constructor called" << endl;
    }
    ~Derived()
    {
        cout << "Derived Destructor called" << endl;
    }
};

int main()
{
    Derived obj;
    return 0;
}

输出结果:

a1 Constructor called
a2 Constructor called
Derived Constructor called
Derived Destructor called
a2 Destructor called
a1 Destructor called 

在定义一个派生类对象时,构造函数的调用顺序:

        基类 >>> 派生类对象成员(按定义顺序) >>> 派生类

析构函数调用顺序恰好相反

//将 Derived 修改如下
class Derived : public a2
{
private:
    a1 obj1;
public:
    Derived()
    {
        cout << "Derived Constructor called" << endl;
    }
    ~Derived()
    {
        cout << "Derived Destructor called" << endl;
    }
};

a2 Constructor called
a1 Constructor called
Derived Constructor called
Derived Destructor called
a1 Destructor called
a2 Destructor called

有参情况

  1. 派生类只需要负责直接基类构造函数的调用

  2. 如果基类构造函数不需要提供参数,则无需在初始化列表中给出

  3. 创建对象构造函数的调用顺序与声明顺序有关,而非在初始化列表中的顺序

  4. 其他初始化项包括对象成员,常成员和引用成员

示例

#include <iostream>
using namespace std;

class Base
{
private:
    static int count;
    int x;
public:
    Base(int i)
    {
        x=i;
        cout<<"Base constructor called"<<count++<<endl;
    }
    void display()
    {
        cout<<"x = "<<x<<endl;
    }
};

class Derived : public Base
{
private:
    Base b;
public:
    Derived (int i): Base(i),b(i)
    {
        cout<<"Derived constructor called"<<endl;
    }
};

int Base::count=0;

int main() 
{
    Derived d(3);
    d.display();
    return 0;
}

多重继承示例

#include <iostream>
using namespace std;

class Grand
{
private:
    int a;
public:
    Grand(int n):a(n)
    {
        cout << "Grand c,a=" << a << endl;
    }
    ~Grand()
    {
        cout << "Grand d" << endl;
    }
};

class Father:public Grand
{
private:
    int b;
public:
    Father(int n1,int n2):Grand(n1),b(n2)
    {
        cout << "Father c,b=" << b << endl;
    }
    ~Father()
    {
        cout << "Father d" << endl;
    }
};

class Mother
{
private:
    int c;
public:
    Mother(int n):c(n)
    {
        cout << "Mother c,c=" << c << endl;
    }
    ~Mother()
    {
        cout << "Mother d" << endl;
    }
};

class Child:public Father,public Mother
{
private:
    int d;
public:
    Child(int n1,int n2,int n3,int n4):Father(n4,n3),Mother(n2),d(n1)
    {
        cout << "Child d=" << d << endl;
    }
    ~Child()
    {
        cout << "Child d" << endl;
    }
};


int main()
{
    Child c(1,2,3,4);
    return 0;
}

Grand c,a=4
Father c,b=3
Mother c,c=2
Child d=1
Child d
Mother d
Father d
Grand d 

三、同名冲突

基类与派生类的同名冲突

同名覆盖原则:新成员名称与基类某个成员同名时,若未加任何特殊标识,访问派生类中新定义的同名成员

需要访问基类:使用 “基类名::” 进行限定

  • 通过派生类的指针或引用,访问的是派生类的同名成员(同名覆盖√)
  • 基类指针/引用,访问基类同名成员
#include <iostream>
using namespace std;

class Base
{
public:
    int a;
    Base(int x)
    {
        a = x;
    }
    void Print()
    {
        cout << "Base::a = " << a << endl;
    }
};

class Derived : public Base
{
public:
    int a;      //欸这里也有个a耶
    Derived(int x, int y) : Base(x)
    {
        a = y;
        Base::a *= 2;
    }
    void Print()
    {
        Base::Print();
        cout << "Derived::a = " << a << endl;
    }
};

void Test1(Base& b)
{
    b.Print();
}

void Test2(Derived& d)
{
    d.Print();
}

int main()
{
    Derived d(200, 300);
    d.Print();
    d.a = 400;
    d.Base::a = 500;
    d.Base::Print();
    Base* pb;
    pb = &d;
    pb->Print();
    Test1(d);
    Derived *pd;
    pd = &d;
    pd->Print();
    Test2(d);

    return 0;
}

多重继承中直接基类的同名冲突

通过域解析符解决

#include <iostream>
using namespace std;

class Base1
{
protected:
    int a;
    Base1(int x)
    {
        a = x;
        cout<<"Base1 a="<<a<<endl;
    }
    void Print()
    {
        cout << "Base::a = " << a << endl;
    }
};

class Base2
{
protected:
    int a;
public:
    Base2(int x)
    {
        a = x;
        cout<<"Base2 a="<<a<<endl;
    }   
};

class Derived:public Base1, public Base2
{
public:
    Derived(int x,int y):Base1(x),Base2(y)
    {
        Base1::a *=2;
        Base2::a *=2;
        cout<<"Derived from Base1::a="<<Base1::a<<endl;
        cout<<"Derived from Base2::a="<<Base2::a<<endl;
    }
};


int main()
{
    Derived d(10,20);
    return 0;
}

共同祖先基类引发的同名冲突

  1. 域解析符
  2. 虚基类

虚基类

virtual 确保虚基类最多被调用一次

#include <iostream>
using namespace std;

class Base 
{
protected:
    int a;
public:
    Base (int x):a(x)
    {
        cout<<"Base a="<<a<<endl;
    }
    ~Base ()
    {
        cout<<"Base destructor"<<endl;
    }
};

class Base1 : public virtual Base
{
protected:
    int b;
public:
    Base1(int x,int y):Base(y),b(x)
    {
        cout<<"Base1 from Base a="<<a<<endl;
        cout<<"Base1 b="<<b<<endl;
    } 
};

class Base2 : public virtual Base 
{
protected:
    int c;
public:
    Base2(int x,int y):Base(y),c(x)
    {
        cout<<"Base2 from Base a="<<a<<endl;
        cout<<"Base2 c="<<c<<endl;
    }
};

class Derived : public Base1, public Base2 
{
public:
    Derived(int x,int y):Base1(x,y),Base2(2*x,2*y),Base(3*x)
    {
        cout<<"a="<<a<<endl;
        cout<<"Base::a="<<Base::a<<endl;
        cout<<"Base1::a="<<Base1::a<<endl;
        cout<<"Base2::a="<<Base2::a<<endl;
        cout<<"b="<<b<<endl;
        cout<<"c="<<c<<endl;
    }
    ~Derived ()
    {
        cout<<"Derived destructor"<<endl;
    }
};

int main() 
{
    Derived d(10,20);
    return 0;
}

其中 Base 类只有一份复制

只有最后一层派生类对虚基类构造函数的调用发挥作用

创建一个对象,构造函数调用次序:

虚基类的构造函数

直接基类的构造函数

对象成员的构造函数

派生类自己的构造函数

 四、赋值兼容规则

使公有派生类可以当作基类来使用

1. 派生类对象 -> 基类对象

2. 派生类对象地址 -> 基类指针

3. 派生类对象指针 -> 基类指针

3.派生类对象 -> 基类引用        

#include <iostream>
using namespace std;

class Base
{
private:
    int b;
public:
    Base(int x):b(x)
    {}
    int getB()
    {
        return b;
    }
};

class Derived : public Base
{
private:
    int d;
public:
    Derived(int x, int y):Base(x), d(y)
    {}
    int getD()
    {
        return d;
    }
};

int main()
{
    Base b(11);
    Derived d(22, 33);
    
    b = d;
    cout << "b.getB() = " << b.getB() << endl;

    Base *bp = &d;
    cout << "bp->getB() = " << bp->getB() << endl;

    Derived *dp = &d;
    Base *bp2 = dp;
    cout << "bp2->getB() = " << bp2->getB() << endl;

    Base &rb = d;
    cout << "rb.getB() = " << rb.getB() << endl;
    
    return 0;
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

--菱形继承--

#include<iostream> using namespace std;class Animal { public:Animal(){m_Age 0;}int m_Age; };//利用虚继承 解决菱形继承的问题 //继承之前 加上关键字 virtual 变为虚继承 // Animal类称为 虚基类 //羊类 class Sheep:virtual public Animal { public:};//驼类 cl…

力扣数据库题库学习(4.28日)--1581.进店却未进行过交易的顾客

1581. 进店却未进行过交易的顾客 问题链接 思路分析 有一些顾客可能光顾了购物中心但没有进行交易。请你编写一个解决方案&#xff0c;来查找这些顾客的 ID &#xff0c;以及他们只光顾不交易的次数。返回以 任何顺序 排序的结果表。 要求&#xff1a; 获取只浏览不消费的…

idea 的使用和安装 以及简介

Java开发工具 大家刚才写代码的时候都是用记事本写的&#xff0c;但是有没有觉得记事本写代码不太方便啊&#xff01;记事本写代码单词写错了没有提示&#xff0c;格式也不好调整&#xff0c;写代码之后还需要我们到命令行使用javac命令手动编译&#xff0c;然后运行。 有没有一…

春秋云镜 CVE-2023-50564

靶标介绍&#xff1a; Pluck-CMS v4.7.18 中的 /inc/modules_install.php 组件&#xff0c;攻击者可以通过上传一个精心制作的 ZIP 文件来执行任意代码。 开启靶场&#xff1a; 1、点击 admin 进入登录界面 2、使用Burp爆破出登录密码为&#xff1a;admin123&#xff0c;使用…

BIM为电力、供水和道路工程无缝集成,助力智慧城市计划

在道路和公用事业工程中利用 Bentley Open 系列应用程序&#xff0c;项目进度加快 10%&#xff0c;节省成本 1,000 万印度卢比 推动基础设施现代化&#xff0c;实现智慧城市愿景 Dholera特别投资区位于印度艾哈迈达巴德西南 100 公里处&#xff0c;毗邻古吉拉特邦的贸易中心&a…

Bert基础(十八)--Bert实战:NER命名实体识别

1、命名实体识别介绍 1.1 简介 命名实体识别&#xff08;NER&#xff09;是自然语言处理&#xff08;NLP&#xff09;中的一项关键技术&#xff0c;它的目标是从文本中识别出具有特定意义或指代性强的实体&#xff0c;并对这些实体进行分类。这些实体通常包括人名、地名、组织…

新闻 | 电子系协同智能中心与昌平区未来高教园及多所高校开展交流,共话智能无人平台建设

2024年4月8日&#xff0c;清华大学电子工程系在北京昌平两岸共盈科技产业园电子系地空协同智能无人平台基地成功举办“美团杯”智能无人机挑战赛&#xff0c;清华大学电子系党委书记沈渊、昌平区未来城管委会校城融合处处长熊玉川、清华大学团委副书记黄峰等出席。此外来自昌平…

【面经】汇总

面经 Java基础集合都有哪些面向对象的三大特点ArrayList和LinkedList的区别&#xff1f;ArrayList底层扩容是怎么实现的&#xff1f;讲一讲HashMap、以及put方法的过程讲一讲HashMap的扩容过程Hashmap为什么要用红黑树而不用其他的树&#xff1f;Java8新特性有哪些LoadFactor负…

Scala 03 —— Scala OOP Extension

Scala 2.1 —— Scala OOP Extension 一、正则 文章目录 Scala 2.1 —— Scala OOP Extension一、正则1.1 Java正则和Scala正则的区别1.2 Java正则和Scala正则的的基本知识点Java正则Scala正则 1.3 练习练习一&#xff1a;使用正则表达式解析日志方法一&#xff1a;使用findAl…

99AI3.3二开稳定版(NineAi内核升级)免授权无后门AI系统源码部署及详细安装教程

99AIv3.3.0是基于 NineAI 二开的可商业化 AI Web 应用&#xff08;免授权&#xff0c;无后门&#xff0c;非盗版&#xff0c;已整合前后端&#xff0c;支持快速部署&#xff09;。未编译源码暂不开源&#xff0c;相比稳定版&#xff0c;开发版进度更快一些。前端改进&#xff1…

【Python】全面掌握 Collections Deque:队列与栈的高效实现及动态内存管理指南

文章目录 第一章&#xff1a;deque 的定义和特性1. 什么是双端队列&#xff08;deque&#xff09;2. deque 与普通列表&#xff08;list&#xff09;的性能差异 第二章&#xff1a;构造函数1. 如何创建一个 deque2. 可选参数 maxlen 的作用和使用场景 第三章&#xff1a;添加和…

vue3使用echarts做树图tree

vue3使用echarts做树图tree 1.安装echarts npm install echarts --save2.在main.js引入 import * as echarts from echarts // 全局方法 app.config.globalProperties.$echarts echarts3.使用 <div id"myChart" :style"{ width: 1000px, height: 1000px …

如何设置“mumu模拟器”使用fiddler抓取APP包?

1、打开fiddler-->tools-->optinons,设置如下信息https信息和connections 2、下载证书tools-->optinons-->https-->actions->Export Root Certificate to Desktop到桌面 3、mumu模拟器&#xff0c;安装证书 1)mumu进入桌面有个文件共享&#xff0c;打开后将桌…

python—字符串与正则表达式

1、编写程序&#xff0c;生成一个由15个不重复的大小写字母组成的列表。 &#xff08;1&#xff09;源代码&#xff1a; import random import string list1 [] while len(list1) < 15: x random.choice(string.ascii_letters) if x not in list1: list1.append(x) print…

pycharm-ieda-phpstorm超级好用插件,一键解释代码

功能&#xff1a;解释你看不懂的代码 当你在写python和Java代码的时候&#xff0c;总有你看不懂的代码&#xff0c;怎么办&#xff1f;csdn搜&#xff1f;那不麻烦&#xff0c;直接插件解决。 来安装&#xff1a;文件-设置 点击插件-Marketplace-搜索通义灵码 安装完成后&…

Qt Creator中变量与函数的注释 - 鼠标悬浮可显示

Qt Creator中变量与函数的注释 - 鼠标悬浮可显示 引言一、变量注释二、函数注释三、参考链接 引言 代码注释在软件开发中起着至关重要的作用。它们不仅有助于开发者理解和维护代码&#xff0c;还能促进团队协作&#xff0c;提高代码的可读性和可维护性。适当的注释应该是简洁明…

VoxAtnNet:三维点云卷积神经网络

VoxAtnNet:三维点云卷积神经网络 摘要IntroductionProposed VoxAtnNet 3D Face PAD3D face point cloud presentation attack Dataset (3D-PCPA) VoxAtnNet: A 3D Point Clouds Convolutional Neural Network for 摘要 面部生物识别是智能手机确保可靠和可信任认证的重要组件。…

16册 | 移动机器人(自动驾驶)系列

此文档整理推荐了16本移动机器人&#xff08;自动驾驶&#xff09;相关的书籍&#xff0c;内容包括&#xff1a;ROS、机器人基础开发、分布式机器人控制、集群机器人控制、嵌入式机器人、多传感器融合等等。 学习&#xff0c;切勿急于求成&#xff0c;读书自学&#xff0c;需多…

栈和队列总结

文章目录 前言一、栈和队列的实现1.栈的具体实现2.循环顺序队列的具体实现 二、栈和队列总结总结 前言 T_T此专栏用于记录数据结构及算法的&#xff08;痛苦&#xff09;学习历程&#xff0c;便于日后复习&#xff08;这种事情不要啊&#xff09;。所用教材为《数据结构 C语言版…

【启明智显技术分享】ESP32系列WiFi无线空中抓包指南

前言&#xff1a; 本文档旨在介绍 windows10 系统下网卡抓包工具(AC-1200)的驱动安装过程、Omnipeek 软件安装过程及Omnipeek软件与网卡抓包工具配合抓包的演示过程。 1、抓包工具(AC-1200)驱动安装 1.1 准备好抓包工具及厂家提供的抓包工具驱动文件 1.2 插上 USB 网卡&…
最新文章