6.C++:继承

news2024/12/24 2:09:49

一、继承

//1.类中的保护和私有在当前类中没有差别;

//2.在继承后的子类中有差别,private在子类中不可见,所以用protected;

class person
{
public:
    void print()
    {
        cout << "name:" << _name << endl;
        cout << "age:" << _age << endl;
    }
protected:     //若换为private,则执行错误
    string _name = "peter";
    int _age = 18;
};

class student: public person
{
protected:
    int stuid;
};
int main()
{
    student s;
    s.print();
    return 0;
}

二、 基类和派生类对象赋值转换

class person
{
protected:
    string _name;
    string _sex;
    int _age;
};
class student: public person
{
protected:
    int stuid;
};
int main()
{
    person p;
    student s;
    //子类和父类之间的赋值兼容规则
    //1.子类对象可以赋值给父类对象/指针/引用
    p = s;
    person* ptr = &s;
    person& ref = s;
    //反过来
    s = p;     //不可以
    student* ptr = &p; //有时候可以
    student& ref = p;
    return 0;
}

指针ptr指向student类中父类的那一部分;

引用ref是子类student中父类那一部分的别名; 


三、继承中的作用域

class person
{
protected:
    string _name = "peter";
    int _num = 111;
};
class student: public person
{
public:
    void print()
    {
        cout << "姓名:" << _name << endl;
        cout << "学号:" << _num << endl;
    }
protected:
    int _num = 999;
};
int main()
{
    student s;
    s.print();   
    return 0;
}
//输出: 姓名:peter
       // 学号:999

//1.两个_num在不同的作用域中,一个在父类,一个在子类,不会报错;

//2.当父类和子类同时有同名成员时,子类的成员隐藏于父类的成员(重定义);

//优先访问子类,现在子类中找,再去父类;

 访问父类_num:

class person
{
protected:
    string _name = "peter";
    int _num = 111;
};
class student: public person
{
public:
    void print()
    {
        cout << "姓名:" << _name << endl;
        cout << "学号:" << _num << endl;
        cout << "学号:" << person::_num << endl; //指定作用域即可
    }
protected:
    int _num = 999;
};
int main()
{
    student s;
    s.print();
    return 0;
}

 //1.A和B的fun构成什么关系?

//重定义(隐藏),不是重载,重载必须在同一个作用域

//函数只要函数名相同,不需要参数相同

class A
{
public:
    void fun()
    {
        cout << "func()" << endl;
    }
};
class B : public A
{
public:
    void fun(int i)
    {
        A::fun();
        cout << "func(int i)->" << i << endl;
    }
};

int main()
{
    B b;
    b.fun(); //执行错误
    b.fun(123456);
    b.A::fun(); //调用A的fun()
    return 0;
}

四、派生类的默认成员函数

class Person
{
public:
    //1.构造函数
    Person(const char* name = "peter")
        : _name(name)
    {
        cout << "Person()" << endl;
    }
    //2.拷贝构造
    Person(const Person& p)
        : _name(p._name)
    {
        cout << "Person(const Person& p)" << endl;
    }
    //3.赋值
    Person& operator=(const Person& p)
    {
        cout << "Person operator=(const Person& p)" << endl;
        if (this != &p)
            _name = p._name;
        return *this;
    }
    //4.析构函数
    ~Person()
    {
        cout << "~Person()" << endl;
    }
protected:
    string _name;
};

class Student : public Person
{
public:
    Student(const char* name, int num)
        : Person(name) //调用父类的构造函数
        , _num(num)
    {
        cout << "Student()" << endl;
    }
    Student(const Student& s)
        : Person(s) //调用父类的拷贝构造
        , _num(s._num)
    {
        cout << "Student(const Student& s)" << endl;
    }
    Student& operator=(const Student& s)
    {
        if (this != &s)
        {
            Person::operator =(s);//重定义,调用父类的person::
            _num = s._num;
        }
        cout << "Student& operator= (const Student& s)" << endl;
        return *this;
    }
    ~Student()  
    {
       // Person::~Person();//与~Person()构成隐藏
        cout << "~Student()" << endl;//调用子类析构后会自动调用父类析构
    }
protected:
    int _num; //学号
};
int main()
{
    Student s1("peter",11);
    Student s2(s1);
    return 0;
}

//输出:

Person()   //父类构造
Student()  //子类构造
Person(const Person& p)  //父类拷贝构造
Student(const Student& s)  //子类拷贝构造
~Student()   //s2析构
~Person()    //子类调用析构,自动调用父类析构
~Student()  //s1析构
~Person()

int main()
{
    Student s1("peter",11);
    Student s3("rose",20);
    s1 = s3;
    return 0;
}

 //输出:

Person()  //s1构造
Student()
Person()  //s2构造
Student()
Person operator=(const Person& p)  //父类赋值
Student& operator= (const Student& s)  //子类赋值
~Student()  //s3析构
~Person()
~Student()  //s1析构
~Person()


如何设计一个不能被继承的类? 

构造函数私有化,不能被继承,对象无法生成

class A
{
private:
    A()
    {}
};
class B :public A
{};

五、友元与继承

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员
class Student; //注意
class Person
{
public:
    friend void Display(const Person& p, const Student& s);
protected:
    string _name;
};
class Student : public Person
{
    friend void Display(const Person& p, const Student& s);
protected:
    int _stuNum; 
};

void Display(const Person& p, const Student& s)
{
    cout << p._name << endl;
    cout << s._stuNum << endl;
}
int main()
{
    Person p;
    Student s;
    Display(p, s);
    return 0;
}

 或者:

class Student;
class Person
{
protected:
    string _name;
};
class Student : public Person
{
    friend void Display(const Person& p, const Student& s);
protected:
    int _stuNum; 
};

void Display(const Person& p, const Student& s)
{
    cout << s._name << endl;
    cout << s._stuNum << endl;
}
int main()
{
    Person p;
    Student s;
    Display(p, s);
    return 0;
}

六、继承与静态成员

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例 。
class Person
{
public:
    Person() 
    { 
        ++_count; 
    }
    string _name; 
    static int _count; 
};
int Person::_count = 0;
class Student : public Person
{
public:
    int _stuNum; 
};
int main()
{
    Person p;
    Student s;
    p._name = "jack";
    s._name = "rose";
    p._count = 1;
    s._count = 2;
    cout << Person::_count << endl;
    return 0;
}

_count放在静态区,只有一个_count,p和s中的_count是一个


七、复杂的菱形继承及菱形虚拟继承

单继承:一个子类只有一个直接父类时称这个继承关系为单继承
多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承
菱形继承:菱形继承是多继承的一种特殊情况

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。在Assistant的对象中Person成员会有两份。

class Person
{
public:
    string _name; // 姓名
};
class Student : public Person
{
protected:
    int _num; //学号
};
class Teacher : public Person
{
protected:
    int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:
    string _majorCourse; // 主修课程
};
void Test()
{
    // 这样会有二义性无法明确知道访问的是哪一个
    Assistant a;
    a._name = "peter";
    // 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决
    a.Student::_name = "xxx";
    a.Teacher::_name = "yyy";
}

解决方法:

class Person
{
public:
    string _name; // 姓名
};
class Student : virtual public Person
{
protected:
    int _num; //学号
};
class Teacher : virtual public Person
{
protected:
    int _id; // 职工编号
};

virual分析:

 


八、继承和组合

//1.public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。
//2.组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。
//3.继承与组合都可以的情况下,优先使用对象组合,而不是类继承 。
// Car和BMW Car和Benz构成is-a的关系
class Car {
protected:
    string _colour = "白色"; // 颜色
    string _num = "陕ABIT00"; // 车牌号
};

class BMW : public Car {
public:
    void Drive() { cout << "好开-操控" << endl; }
};

class Benz : public Car {
public:
    void Drive() { cout << "好坐-舒适" << endl; }
};
// Tire和Car构成has-a的关系
class Tire {
protected:
    string _brand = "Michelin"; // 品牌
    size_t _size = 17; // 尺寸
};
class Car {
protected:
    string _colour = "白色"; // 颜色
    string _num = "陕ABIT00"; // 车牌号
    Tire _t; // 轮胎
};

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

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

相关文章

④【Shiro】Shiro框架进行敏感信息加密

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ ④【Shiro】Shiro框架进行敏感信息加密 实际系…

分布式调度器timer和spring task

1. Timer&#xff08;了解&#xff09; 一、Timer使用方式 Task1 public class Task1 extends TimerTask {Overridepublic void run(){System.out.println("com.aware.Task run");} } Task2 public class Task2 extends TimerTask {Overridepublic void run(){…

如何判断软件测试公司报告是否权威

在当今数字化浪潮中&#xff0c;软件测试报告已成为评估软件性能、确保用户体验、发掘潜在问题的关键所在。然而&#xff0c;面对众多软件测试公司及其纷繁复杂的报告&#xff0c;如何洞察其权威性成为一项亟待解决的任务。本文旨在探讨如何精准判别软件测试公司报告的权威性&a…

React Ant Design 简单实现如何选中图片

效果&#xff1a; 代码&#xff1a; 定义的初始值和方法 const [selected, setSelected] useState(0); // 表示当前选中的图片索引const handleClick (index) > {if (selected index) {setSelected(null); // 如果点击的是已选中的图片&#xff0c;则取消选中状态} else…

AI大模型日报#0418:Stable Diffusion 3开放API、Meta新研究让AI Agent理解物理世界

导读&#xff1a; 欢迎阅读《AI大模型日报》&#xff0c;内容基于Python爬虫和LLM自动生成。目前采用“文心一言”生成了每条资讯的摘要。标题: 微软刚发布了VASA-1 这个人工智能可以让单张图像具有生动的说话和歌唱能力 摘要: 微软发布了VASA-1人工智能&#xff0c;它能使单…

java算法day56 | 动态规划part15 ● 392.判断子序列 ● 115.不同的子序列

392.判断子序列 动规五部曲&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j] 表示以下标i-1为结尾的字符串s&#xff0c;和以下标j-1为结尾的字符串t&#xff0c;相同子序列的长度为dp[i][j]。确定递推公式 在确定递推公式的时候&#xff0c;…

显示msvcp140.dll丢失要如何解决?这5种方法高效修复msvcp140.dll

msvcp140.dll是Microsoft Visual C Redistributable软件包中的一个文件&#xff0c;主要用于支持使用C编程语言编写的软件的正常运行。如果你的电脑出现缺少msvcp140.dll的错误消息&#xff0c;可能会影响到某些程序的启动和运行。然而&#xff0c;不必过度担心&#xff0c;因为…

iText 5

依赖 implementation com.itextpdf:itextpdf:5.5.13.3implementation com.itextpdf:itext-asian:5.2.0implementation com.alibaba:fastjson:1.2.83compileOnly org.projectlombok:lombok:1.18.22annotationProcessor "org.projectlombok:lombok:1.18.22"测试 impor…

找不到api-ms-win-crt-runtime-l1-1-0.dll文件5种解决方法

在日常使用计算机的过程中&#xff0c;我们时常会遭遇各类意想不到的问题&#xff0c;其中之一就是“api-ms-win-crt-runtime-l1-1-0.dll丢失”。这个错误通常发生在Windows操作系统中&#xff0c;它表示一个动态链接库文件丢失或损坏。这个问题可能会导致某些应用程序无法正常…

【Vue脚手架】

初始化脚手架 如果下载缓慢请配置npm淘宝镜像&#xff1a; npm config set registry http://registry.npm.taobao.org 全局安装vue脚手架&#xff1a; vue/clinpm install -g vue/cli 1. 创建项目使用命令 vue create xxx 注&#xff1a;后面有选择安装版本&#xff0c;请注意选…

授权协议OAuth 2.0之除了授权码许可还有什么授权流程?

写在前面 源码 。 本文看下OAuth2.0的另外3中授权流程&#xff0c;资源拥有者凭据许可&#xff0c;客户端许可&#xff0c;隐式许可。分别看下具体的使用流程以及该使用场景。 1&#xff1a;资源拥有者凭据许可 资源拥有者凭据许可&#xff0c;这里资源拥有者的凭据是什么呢&…

Vue源码解读学习

Vue源码 观察者模式 & 发布订阅 观察者模式&#xff1a;中心一对多 系统单点间的灵活和拓展&#xff08;广播的方式&#xff09; 发布订阅&#xff1a;将注册列表遍历发布给订阅者 initInject initState initProvide他们挂载顺序为什么这样设计&#xff1f; initstate…

MySQL行格式(row format)

MySQL行格式&#xff08;row format&#xff09; 表的行格式决定了其行的物理存储方式&#xff0c;这反过来又会影响查询和 DML 操作的性能。随着单个磁盘页面容纳更多行&#xff0c;查询和索引查找可以更快地工作&#xff0c;缓冲池中需要的高速缓存内存更少&#xff0c;写出…

京西商城——前端项目的创建以及前后端联调

创建VUE项目 在jingxi_shop_project文件夹中再创建一个 frontend 文件夹用来存放前端项目 /jingxi_shop_project/backend/jingxi_shop_project....../frontend/jingxi_shop_web......首先要安装 node.js 和 VUE cli&#xff0c;进入到项目目录内创建项目 vue create jingxi_…

[Vision Board创客营]学习片上Flash移植FAL

文章目录 [Vision Board创客营]学习片上Flash移植FAL介绍环境搭建使用组件测试porbeerasewriteread 结语 [Vision Board创客营]学习片上Flash移植FAL 水平较菜&#xff0c;大佬轻喷。&#x1f630;&#x1f630;&#x1f630; 介绍 &#x1f680;&#x1f680;Vision-Board 开…

解锁流量密码:如何利用HubSpot打造高效的获客策略?(下)

在当今数字化时代&#xff0c;流量是企业成功的关键。HubSpot作为一款全面的营销自动化工具&#xff0c;为我们提供了强大的支持&#xff0c;帮助企业打造高效的流量获取策略。接下来&#xff0c;我们将从社交媒体与SEO优化、自动化营销流程、数据分析与效果评估以及流量获取策…

【R语言】组合图:散点图+箱线图+平滑曲线图+柱状图

用算数运算符轻松组合不同的ggplot图&#xff0c;如图&#xff1a; 具体代码如下&#xff1a; install.packages("devtools")#安装devtools包 devtools::install_github("thomasp85/patchwork")#安装patchwork包 library(ggplot2) library(patchwork) #p1是…

Linux进程和任务管理

目录 一.程序和进程的关系 程序 进程 线程 线程与进程的区别 二.查看进程信息ps 方法一 常用选项 方法二 三.TOP动态查看进程信息 进程信息区各列解释 top常用命令 系统查看命令总结 查看进程信息pgrep 查看进程树pstree 四.控制进程 进程的启动方式 进程的前…

electron的webview和内嵌网页如何通信

在 Electron 的世界里&#xff0c;webview 标签相当于一个小盒子&#xff0c;里面可以装一个完整的网页&#xff0c;就像一个迷你浏览器。当你想和这个小盒子里的内容说话时&#xff08;也就是进行通信&#xff09;&#xff0c;这里有几个方法可以帮你做到&#xff1a; 这里只写…

LIUNX文件系统

目录 1.磁盘的物理结构 2.CHS定位法 3.磁盘的逻辑存储 4.系统层面 inode.block[15] 创建文件的流程 查找文件的流程 了解文件系统&#xff0c;首先要了解磁盘是如何存储和读取数据的。 1.磁盘的物理结构 可以理解这个盘上有很多的小磁铁&#xff0c;通过旋转盘面和摆动…