C++基础 | 继承和派生

耦合度,高内聚,低耦合
程序设计追求高内聚,低耦合
高内聚指一个函数干的事情极少,甚至只干一件事情
低耦合是类之间的关系越少越好

继承

继承的耦合度很高,但是方便不用写太多代码

在 C++中可重用性(software reusability)是通过继承(inheritance)这一机制来 实现的。

定义:
类的继承,是新的类从已有类那里得到已有的特性。或从已有类产生新类 的过程就是类的派生。原有的类称为基类或父类,产生的新类称为派生类或子类。
派生与继承,是同一种意义两种称谓。

#include <iostream>
using namespace std;
class Student
{
public:
    void dis() {
        cout<<name<<endl;
        cout<<age<<endl;
}
      string name;
      int age; 
};

class Student2:public Student
{
public:
    Student2(string n,int a,char s,float f)
    {
        name = n; age = a; sex = s; score = f;
    }
    void dis() {
        Student::dis();
        cout<<sex<<endl;
        cout<<score<<endl;
    }
     char sex;
     float score;
};

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


20988794-5f4f930f1c10d98d.png
屏幕快照 2020-02-02 下午8.26.13.png

几点说明: 1,全盘接收,除了构造器与析构器。基类有可能会造成派生类的成员冗余,所以 说基类是需设计的。
2,派生类有了自己的个性,使派生类有了意义。

派生类的构造函数是一定会调用基类的构造函数的,一般都是将继承过来的变量用初始化列表来初始化。如果不想写初始化列表的话,基类要有无参构造函数。

一个派生类可以同时有多个基类,这种情况称为多重继承,派生类只有一个 基类, 称为单继承。

继承的方式

语法:
class 派 类名:[继承 式] 基类名 {
派 类成员声明;
};

public公有继承:
当类的继承方式为公有继承时,基类的公有和保护成员的访问属性在派生
类中 不变,而基类的私有成员不可访问。

protected保护继承:
保护继承中,基类的公有成员和私有成员都以保护成员的身份出现在派生
类 中,而基类的私有成员不可访问。

private私有继承:
当类的继承方式为私有继承时,基类中的公有成员和保护成员都以私有成
员身 份出现在派生类中,而基类的私有成员在派生类中不可访问。

private成员在子类中依然存在,但是却无法访问到。不论何种方式继承 基类,派生类都不能直接使用基类的私有成员 。

#include <iostream>
using namespace std;
class A
{
private:
    int a;
protected:
    int b;
public:
    int c;
    A() {
        a = 0;
        b = 0;
        c = 0; 
    }
    void set(int a, int b, int c)
    {
        this->a = a;
        this->b = b;
        this->c = c;
    } 
};
class B : public A
{
public:
    void print()
    {
        cout<<"a ="<<a<<endl;  //不能访问,a是基类的private
        cout<<"b ="<<b<<endl;
        cout<<"c ="<<c<<endl;
    } 
};
class C : protected A
{
public:
    void print()
    {
        cout<<"a ="<<a<<endl;   //不能访问,a是基类的private
        cout<<"b ="<<b<<endl;
        cout<<"c ="<<c<<endl;
    } 
};
class D : private A
{
public:
void print()
{
cout<<"a = "<<a<<endl;  //不能访问,a是基类的private
cout<<"b = "<<b<<endl; 
cout<<"c = "<<c<<endl; 
} };
int main(void)
{
    A aa;
    B bb;
    C cc;
    D dd;
    aa.c = 100;
    bb.c = 100;
    cc.c = 100;
    dd.c = 100;

    aa.set(1, 2, 3); 
    bb.set(10, 20, 30); 
    cc.set(40, 50, 60); //不能访问,set是protected成员
    dd.set(70, 80, 90); //不能访问,set是private成员
    bb.print(); 
    cc.print(); 
    dd.print(); 
    return 0; 
}
类型兼容性原则

类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类 的对象来替代。通过公有继承,派生类得到了基类中除构造函数、析构函数之 外的所有成员。这样,公有派生类实际就具备了基类的所有功能,凡是基类能 解决的问题,公有派生类都可以解决。

类型兼容规则中所指的替代包括以下情况:
子类对象可以当作父类对象使用
子类对象可以直接赋值给父类对象
子类对象可以直接初始化父类对象
父类指针可以直接指向子类对象
父类引用可以直接引用子类对象

在替代之后,派生类对象就可以作为基类的对象使用,但是只能使用从基类继承的成员。
子类就是特殊的父类 (base *p = &child;)

#include <iostream>
using namespace std;
class Parent
{
public:
    void printP()
    {
        cout << "parent...." << endl;
    }
};
class Child : public Parent
{
    public:
        void printC()
        {
            cout << "child..." << endl;
        } 
};
void print01(Parent  *p)
{
    p->printP();
}
void print02(Parent  &p)
{
    p.printP();
}
int main() {
    /*
    //Parent p;
    //Child c=p;    //p对象填充不满c对象空间

    Child c;
    Parent p=c; //c对象所占用的内存空间>=p对象占用空间,能够填充满p对象所需要空间
    */

    Child c1;
    c1.printC();
    Parent *p = NULL; //可以用父类指针指向子类对象 
    p = &c1;
    p->printP();    //执行父类的函数
    Child   c2;
    Parent  p2;
    print01(&p2);
    print01(&c2); // 父类指针指向子类对象
    print02(p2);
    print02(c2); // 父类引用指向子类对象
    //第二层含义   用子类初始化父类对象 
    Child c3;
    Parent p3 = c3;
return 0;
}
继承中的构造和析构

在子类对象构造时,需要调用父类构造函数对其继承得来的成员进行初始化.
在子类对象析构时,需要调用父类析构函数对其继承得来的成员进行清理.

继承中构造析构调用原则:
1、子类对象在创建时会首先调用父类的构造函数
2、父类构造函数执行结束后,执行子类的构造函数
3、当父类的构造函数有参数时,需要在子类的初始化列表中显示调用
4、析构函数调用的先后顺序与构造函数相反

先构造父类,再构造成员变量、最后构造自己
先析构自己,在析构成员变量、最后析构父类

#include <iostream>
using namespace std;
class Object
{
public:
    Object(const char* s)
    {
        cout<<"Object()"<<" "<<s<<endl;
    }
~Object() {
        cout<<"~Object()"<<endl;
    }
};
class Parent : public Object
{
public:
    Parent(const char* s) : Object(s)
    {
        cout<<"Parent()"<<" "<<s<<endl;
    }
~Parent() {
        cout<<"~Parent()"<<endl;
    }
};
class Child : public Parent
{
public:
    Child() : o2("o2"), o1("o1"), Parent("Parameter from Child!")
    {
        cout<<"Child()"<<endl;
    }
~Child() {
        cout<<"~Child()"<<endl;
    }
    private:
    Object o1;
Object o2; };
void run() {
    Child child;
}
int main(int argc, char *argv[])
{
run();
return 0;
}


运行结果:
Object() Parameter from Child!
Parent() Parameter from Child!
Object() o1
Object() o2
Child()
~Child()
~Object()
~Object()
~Parent()
~Object()
继承中同名成员变量处理方法

1、当子类成员变量与父类成员变量同名时
2、子类依然从父类继承同名成员
3、在子类中通过作用域分辨符::进行同名成员区分(在派生类中使用基
类的同名成员,显式地使用类名限定符)
4、同名成员存储在内存中的不同位置

派生类中的static关键字

1.基类定义的静态成员,将被所有派生类共享

  1. 根据静态成员自身的访问特性和派生类的继承方式,在类层次体系中具 有不同的访问性质 (遵守派生类的访问控制)
    3.派生类中访问静态成员,用以下形式显式说明:
    类名 :: 成员
    或通过对象访问:对象名 . 成员

多继承与虚继承

多继承

class C:public c1, public c2 {}

虚继承virtual

如果一个派生类从多个基类派生,而这些基类又有一个共同的基类,则在对该基类中声明的名字进行访问时,可能产生二义性

如果在多条继承路径上有一个公共的基类,那么在继承路径的某处汇合点,这个公共基类就会在派生类的对象中产生多个基类子对象

要使这个公共基类在派生类中只产生一个子对象,必须对这个基类声明为虚继承,使这个基类成为虚基类。

虚继承声明使用关键字 virtual

如:class B1: virtual public B { }

标题“51单片机通过MPU6050-DMP获取姿态角例程”解析 “51单片机通过MPU6050-DMP获取姿态角例程”是一个基于51系列单片机(一种常见的8位微控制器)的程序示例,用于读取MPU6050传感器的数据,并通过其内置的数字运动处理器(DMP)计算设备的姿态角(如倾斜角度、旋转角度等)。MPU6050是一款集成三轴加速度计三轴陀螺仪的六自由度传感器,广泛应用于运动控制姿态检测领。该例程利用MPU6050的DMP功能,由DMP处理复杂的运动学算法,例如姿态融合,将加速度计陀螺仪的数据进行整合,从而提供稳定且实时的姿态估计,减轻主控MCU的计算负担。最终,姿态角数据通过LCD1602显示屏以字形式可视化展示,为用户提供直观的反馈。 从标签“51单片机 6050”可知,该项目主要涉及51单片机MPU6050传感器这两个关键硬件组件。51单片机基于8051内核,因编程简单、成本低而被广泛应用;MPU6050作为惯性测量单元(IMU),可测量设备的线性角速度。文件名“51-DMP-NET”可能表示这是一个与51单片机及DMP相关的网络资源或代码库,其中可能包含C语言等适合51单片机的编程语言的源代码、配置文件、用户手册、示例程序,以及可能的调试工具或IDE项目文件。 实现该项目需以下步骤:首先是硬件连接,将51单片机与MPU6050通过I2C接口正确连接,同时将LCD1602连接到51单片机的串行数据线控制线上;接着是初始化设置,配置51单片机的I/O端口,初始化I2C通信协议,设置MPU6050的工作模式数据输出速率;然后是DMP配置,启用MPU6050的DMP功能,加载预编译的DMP固件,并设置DMP输出数据的中断;之后是数据读取,通过中断服务程序从DMP接收姿态角数据,数据通常以四元数或欧拉角形式呈现;再接着是数据显示,将姿态角数据转换为可读的度数格
MathorCup高校数学建模挑战赛是一项旨在提升学生数学应用、创新团队协作能力的年度竞赛。参赛团队需在规定时间内解决实际问题,运用数学建模方法进行分析并提出解决方案。2021年第十一届比赛的D题就是一个典型例子。 MATLAB是解决这类问题的常用工具。它是一款强大的数值计算编程软件,广泛应用于数学建模、数据分析科学计算。MATLAB拥有丰富的函数库,涵盖线性代数、统计分析、优化算法、信号处理等多种数学操作,方便参赛者构建模型实现算法。 在提供的文件列表中,有几个关键文件: d题论文(1).docx:这可能是参赛队伍对D题的解答报告,详细记录了他们对问题的理解、建模过程、求解方法结果分析。 D_1.m、ratio.m、importfile.m、Untitled.m、changf.m、pailiezuhe.m、huitu.m:这些是MATLAB源代码文件,每个文件可能对应一个特定的计算步骤或功能。例如: D_1.m 可能是主要的建模代码; ratio.m 可能用于计算某种比例或比率; importfile.m 可能用于导入数据; Untitled.m 可能是未命名的脚本,包含临时或测试代码; changf.m 可能涉及函数变换; pailiezuhe.m 可能与矩阵的排列组合相关; huitu.m 可能用于绘制回路图或流程图。 matlab111.mat:这是一个MATLAB数据文件,存储了变量或矩阵等数据,可能用于后续计算或分析。 D-date.mat:这个文件可能包含与D题相关的特定日期数据,或是模拟过程中用到的时间序列数据。 从这些文件可以推测,参赛队伍可能利用MATLAB完成了数据预处理、模型构建、数值模拟结果可视化等一系列工作。然而,具体的建模细节解决方案需要查看解压后的文件内容才能深入了解。 在数学建模过程中,团队需深入理解问题本质,选择合适的数学模
以下是关于三种绘制云图或等高线图算法的介绍: 一、点距离反比插值算法 该算法的核心思想是基于已知数据点的值,计算未知点的值。它认为未知点的值与周围已知点的值相关,且这种关系与距离呈反比。即距离未知点越近的已知点,对未知点值的影响越大。具体来说,先确定未知点周围若干个已知数据点,计算这些已知点到未知点的距离,然后根据距离的倒数对已知点的值进行加权求,最终得到未知点的值。这种方法简单直观,适用于数据点分布相对均匀的情况,能较好地反映数据在空间上的变化趋势。 二、双线性插值算法 这种算法主要用于处理二维数据的插值问题。它首先将数据点所在的区划分为一个个小的矩形单元。当需要计算某个未知点的值时,先找到该点所在的矩形单元,然后利用矩形单元四个顶点的已知值进行插值计算。具体过程是先在矩形单元的一对对边上分别进行线性插值,得到两个中间值,再对这两个中间值进行线性插值,最终得到未知点的值。双线性插值能够较为平滑地过渡数据值,特别适合处理图像缩放、地理数据等二维场景中的插值问题,能有效避免插值结果出现明显的突变。 三、面距离反比 + 双线性插值算法 这是一种结合了面距离反比双线性插值两种方法的算法。它既考虑了数据点所在平面区对未知点值的影响,又利用了双线性插值的平滑特性。在计算未知点的值时,先根据面距离反比的思想,确定与未知点所在平面区相关的已知数据点集合,这些点对该平面区的值有较大影响。然后在这些已知点构成的区内,采用双线性插值的方法进行进一步的插值计算。这种方法综合了两种算法的优点,既能够较好地反映数据在空间上的整体分布情况,又能保证插值结果的平滑性,适用于对插值精度数据平滑性要求较高的复杂场景。
内容概要:本文详细介绍并展示了基于Java技术实现的微信小程序外卖点餐系统的设计与实现。该系统旨在通过现代信息技术手段,提升外卖点餐管理的效率用户体验。系统涵盖管理员、外卖员、餐厅用户四个角色,提供了包括菜品管理、订单管理、外卖员管理、用户管理等功能模块。后台采用SSM框架(Spring + Spring MVC + MyBatis)进行开发,前端使用微信小程序,数据库采用MySQL,确保系统的稳定性安全性。系统设计遵循有效性、高可靠性、高安全性、先进性采用标准技术的原则,以满足不同用户的需求。此外,文章还进行了详细的可行性分析技术选型,确保系统开发的合理性与可行性。 适用人群:计算机科学与技术专业的学生、从事Java开发的技术人员、对微信小程序开发感兴趣的开发者。 使用场景及目标:①为中小型餐饮企业提供低成本、高效的外卖管理解决方案;②提升外卖点餐的用户体验,实现便捷的点餐、支付评价功能;③帮助传统餐饮企业通过数字化工具重构消费场景,实现线上线下一体化运营。 其他说明:该系统通过详细的系统分析、设计实现,确保了系统的稳定性易用性。系统不仅具备丰富的功能,还注重用户体验数据安全。通过本项目的开发,作者不仅掌握了微信小程序Java开发技术,还提升了独立解决问题的能力。系统未来仍需进一步优化完善,特别是在功能模块的细化用户体验
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值