C/C++知识点之C++语言学习(十)——继承与派生
小标 2019-04-22 来源 : 阅读 1198 评论 0

摘要:本文主要向大家介绍了C/C++知识点之C++语言学习(十)——继承与派生,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了C/C++知识点之C++语言学习(十)——继承与派生,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。


一、类之间的关系


1、类之间的组合关系


组合关系是整体与部分的关系。
组合关系的特点:
A、将其它类的对象作为当前类的成员使用
B、当前类的对象与成员对象的生命周期相同
C、成员对象在用法上与普通对象相同
Computer类由其它多个部件类组合而成,当Computer销毁时,其它部件对象同时销毁。


#include

using namespace std;

class Memory
{
public:
    Memory()
    {
        cout << "Memory()" << endl;
    }
    ~Memory()
    {
        cout << "~Memory()" << endl;
    }
};

class Disk
{
public:
    Disk()
    {
        cout << "Disk()" << endl;
    }
    ~Disk()
    {
        cout << "~Disk()" << endl;
    }
};

class CPU
{
public:
    CPU()
    {
        cout << "CPU()" << endl;
    }
    ~CPU()
    {
        cout << "~CPU()" << endl;
    }
};

class MainBoard
{
public:
    MainBoard()
    {
        cout << "MainBoard()" << endl;
    }
    ~MainBoard()
    {
        cout << "~MainBoard()" << endl;
    }
};

class Computer
{
    Memory mMem;
    Disk mDisk;
    CPU mCPU;
    MainBoard mMainBoard;
public:
    Computer()
    {
        cout << "Computer()" << endl;
    }
    void power()
    {
        cout << "power()" << endl;
    }
    void reset()
    {
        cout << "reset()" << endl;
    }
    ~Computer()
    {
        cout << "~Computer()" << endl;
    }
};

int main(int argc, char *argv[])
{
    Computer c;
    c.reset();
    return 0;
}


2、类之间的继承关系


继承关系是类之间的父子关系。继承关系的特点如下:
A、子类拥有父类的所有属性和行为
B、子类也是一种特殊的父类
C、子类对象可以当父类对象使用
D、子类中可以添加父类没有的属性和方法
E、子类对象可以直接初始化为父类对象
F、子类对象可以直接赋值给父类对象
G、继承是面向对象编程中代码复用的重要手段


#include

using namespace std;

class Parent
{
public:
    Parent(int i = 0)
    {
        member = i;
    }
    void method()
    {
        cout << "member = " << member << endl;
    }
private:
    int member;
};

class Child : public Parent
{
public:
    Child(int i = 0, int j = 0):Parent(i)
    {
        childMember = j;
    }
    void childMethod()
    {
        method();
        cout << "childMember = "<< childMember << endl;
    }
private:
    int childMember;
};

int main(int argc, char *argv[])
{
    Child child(1,2);
    child.method();
    child.childMethod();
    return 0;
}


3、类成员的访问级别选择


定义类时根据类的设计需求确定成员的访问级别,规则如下:
A、public修饰的成员可以被外部访问。
B、protected修饰的成员不可以被外部访问,但可以被子类访问。
C、private修饰的成员不可以被外部和子类访问。


#include

using namespace std;

class Parent
{
public:
    Parent(int a = 0, int b = 0, int c = 0)
    {
       pub = a;
       pro = b;
       pri = c;
    }
    void method()
    {
        cout << "pub = " << pub << endl;
        cout << "pro = " << pro << endl;
        cout << "pri = " << pri << endl;
    }
public:
    int pub;
protected:
    int pro;
private:
    int pri;
};

class Child : public Parent
{
public:
    Child(int a = 0, int b = 0):Parent(a, b)
    {

    }
    void childMethod()
    {
        pub = 100;
        pro = 200;
        //pri = 300;//error,子类不可见
    }
};

int main(int argc, char *argv[])
{
    Parent parent(1,2);
    parent.pub = 1000;
    //parent.pro = 2000;//error,外部不可见
    //parent.pri = 3000;//error,外部不可见
    Child child(1,2);
    child.pub = -1000;
    //child.pro = -2000;//error,外部不可见
    //child.pri = -3000;//error,外部不可见
    child.childMethod();
    return 0;
}


二、继承


1、继承简介


在C++编程中,软件可重用性(software reusability)是通过继承(inheritance)机制来实现的。类的继承,是新的类从已有类得到已有的特性。从已有类产生新类的过程就是类的派生。原有的类称为基类或父类,产生的新类称为派生类或子类。
继承是一种封装模型之间关系的抽象,是不同封装模型的层次分类。


2、派生类的定义


派生类的声明:


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


如果一个派生类同时有多个基类,称为多重继承;如果派生类只有一个基类,称为单继承。


3、继承方式


继承方式规定了如何访问基类继承的成员。继承方式有public、 private,、protected。继承方式指定了派生类成员以及类外对象对于从基类继承来的成员的访问权限。继承方式如下:
A、公有继承
基类的公有成员和保护成员在派生类中保持原有访问属性,其私有成员仍为基类的私有成员。
B、私有继承
基类的公有成员和保护成员在派生类中成了私有成员,其私有成员仍为基类的私有成员。
C、保护继承
基类的公有成员和保护成员在派生类中成了保护成员,其私有成员仍为基类的私有成员。
不同继承方式下父类成员的访问级别如下:

继承成员的访问属性 = Max{继承方式,父类成员的访问属性}


4、默认继承方式


使用class关键字定义派生类时,默认继承方式为private。
使用struct关键字定义派生类时,默认继承方式为public。
C++工程项目中,通常只使用public继承方式。


5、不同继承方式示例


#include

using namespace std;

class Parent
{
public:
    Parent(int a = 0, int b = 0, int c = 0)
    {
       pub = a;
       pro = b;
       pri = c;
    }
public:
    int pub;
protected:
    int pro;
private:
    int pri;
};

class ChildA : public Parent
{
public:
    ChildA(int a = 0, int b = 0):Parent(a, b)
    {
    }
    void print()
    {
        cout << "pub = " << pub << endl;
        cout << "pro = " << pro << endl;
        //cout << "pri = " << pri << endl;//error,私有成员不可见
    }
};

class ChildB : protected Parent
{
public:
    ChildB(int a = 0, int b = 0):Parent(a, b)
    {

    }
    void print()
    {
        cout << "pub = " << pub << endl;
        cout << "pro = " << pro << endl;
        //cout << "pri = " << pri << endl;//error,私有成员不可见
    }
};

class ChildC : private Parent
{
public:
    ChildC(int a = 0, int b = 0):Parent(a, b)
    {
    }
    void print()
    {
        cout << "pub = " << pub << endl;
        cout << "pro = " << pro << endl;
        //cout << "pri = " << pri << endl;//error,私有成员不可见
    }
};
//默认继承方式
class ChildD :  Parent
{
public:
    ChildD(int a = 0, int b = 0):Parent(a, b)
    {
    }
    void print()
    {
        cout << "pub = " << pub << endl;
        cout << "pro = " << pro << endl;
        //cout << "pri = " << pri << endl;//error,私有成员不可见
    }
};

int main(int argc, char *argv[])
{
    ChildA childa(1000,2000);
    childa.pub = 0;
    //childa.pro = 2000;//error,外部不可见
    //childa.pri = 3000;//error,外部不可见
    childa.print();

    ChildB childb(1001,2001);
    //childb.pub = 1001;//error,外部不可见
    //childb.pro = 2001;//error,外部不可见
    //childb.pri = 3001;//error,外部不可见
    childb.print();

    ChildC childc(1002,2002);
    //childc.pub = 1002;//error,外部不可见
    //childc.pro = 2002;//error,外部不可见
    //childc.pri = 3002;//error,外部不可见
    childc.print();

    ChildD childd(1003,2003);
    //childd.pub = 1003;//error,外部不可见
    //childd.pro = 2003;//error,外部不可见
    //childd.pri = 3003;//error,外部不可见
    childd.print();

    return 0;
}


三、派生类


1、派生类简介


派生类中的成员包含两大部分,一类是从基类继承过来的,一类是自己增加的成员。从基类继承的成员表现其共性,而新增的成员体现其个性。
派生类中由基类继承而来的成员的初始化工作还是由基类的构造函数完成,然后派生类中新增的成员在派生类的构造函数中初始化。派生类没有继承基类的构造函数和析构函数。


2、派生类的构造函数


派生类的构造函数语法如下:


派生类名::派生类名(参数总表)
:基类名(参数表),内嵌子对象(参数表)
{
    派生类新增成员的初始化语句; //也可出现在参数列表中
}


子类构造函数必须对继承来的成员进行初始化,可以直接通过初始化列表或赋值方式进行,也可以调用父类构造函数进行初始化。
父类构造函数在子类中的调用方式:
A、默认调用,适用于无参构造函数和使用默认参数的构造函数
B、显示调用,适用于所有父类构造函数,通过初始化列表调用


#include
#include

using namespace std;

class Parent
{
public:
    Parent()
    {
        cout << "Parent()" << endl;
    }
    Parent(string s)
    {
        cout << "Parent(string s): " << s << endl;
    }
    ~Parent()
    {
        cout << "~Parent()" << endl;
    }
};

class Child : public Parent
{
public:
    //隐式调用父类的无参构造函数或默认参数构造函数
    Child()
    {
        cout << "Child()" << endl;
    }
    //显示调用父类构造函数,如果不显示调用,默认调用
    //父类的无参构造函数或默认参数构造函数
    Child(string s):Parent(s)
    {
        name = s;
        cout << "Child(): " << s << endl;
    }
    ~Child()
    {
        cout << "~Child(): " << name << endl;
    }
private:
    string name;
};

int main(int argc, char *argv[])
{

    Child child1("bauer");
    // output:
    // Parent(string s): bauer
    // Child(): bauer
    // ~Child(): bauer
    // ~Parent()

    return 0;
}


构造函数的调用顺序不以初始化列表中的调用顺序进行,而是根据类中对成员变量声明的顺序进行调用。如果基类中没有默认构造函数(无参),那么在派生类的构造函数中必须显示调用基类构造函数,以初始化基类成员。
派生类对象创建时构造函数的调用顺序如下:
A、调用基类构造函数,调用顺序按照基类被继承时声明的顺序(从左到右);
B、调用成员变量的构造函数,调用顺序按照成员变量在类中声明的顺序;
C、调用派生类自身的构造函数。
子类构造函数中,要么显示的调用父类的构造函数(传参),要么隐式的调用。发生隐式调用时,父类要有无参构造函数或是可以包含无参构造函数的默认参数函数。子类构造函数必须对继承而来的成员进行初始化,可以通过初始化列表或者赋值的方法进行初始化,也可以通过调用父类构造函数进行初始化。
子类对象创建时构造函数的调用顺序如下:
A、调用父类的构造函数
B、调用成员变量的构造函数
C、调用类自身的构造函数


#include

using namespace std;

class Parent
{
public:
    Parent()
    {
        cout << "Parent()" << endl;
    }
    Parent(string s)
    {
        cout << "Parent(string s): " << s << endl;
    }
    ~Parent()
    {
        cout << "~Parent()" << endl;
    }
};

class Member
{
public:
    Member(int i = 0)
    {
        this->i = i;
        cout << "Member(int i = 0) i = " << i << endl;
    }
    ~Member()
    {
        cout << "~Member() i = " << i << endl;
    }
private:
    int i;
};

class Child : public Parent
{
public:
    //隐式调用父类的无参构造函数或默认参数构造函数
    Child()
    {
        cout << "Child()" << endl;
    }
    //显示调用父类构造函数,如果不显示调用,默认调用
    //父类的无参构造函数或默认参数构造函数
    Child(string s, int i):Parent(s),member(i)
    {
        name = s;
        cout << "Child(): " << s << endl;
    }
    ~Child()
    {
        cout << "~Child(): " << name << endl;
    }
private:
    string name;
    Member member;
};

int main(int argc, char *argv[])
{
    Child childA("bauer", 10);
    // output:
    // Parent(string s): bauer
    // Member(int i = 0) i = 10
    // Child(): bauer
    // ~Child(): bauer
    // ~Member() i = 10
    // ~Parent()

    return 0;
}


3、派生类的拷贝构造函数


派生类拷贝构造函数的定义如下:


派生类::派生类(const 派生类& another)
:基类(another),派生类新成员(another.新成员)
{
}


派生类中的默认拷贝构造函数会调用父类中默认或自实现拷贝构造函数,若派生类中自实现拷贝构造函数,则必须显示的调用父类的拷贝构造函数。


#include
#include

using namespace std;

class Student
{
public:
    Student(string sn,int n,char s)
    {
        name = sn;
        num = n;
        sex = s;
       cout << "Student(string sn,int n,char s)" << endl;
    }
    Student(const Student& another)
    {
        name = another.name;
        num = another.num;
        sex = another.sex;
    }
    ~Student()
    {
        cout << "~Student()" << endl;
    }
    void print()
    {
        cout << name << endl;
        cout << num << endl;
        cout << sex << endl;
    }
private:
    string name;
    int num;
    char sex;
};

class Graduate : public Student
{
public:
    Graduate(string sn,int in,char cs,int fs):Student(sn, in, cs)
    {
        salary = fs;
        cout << "Graduate(string sn,int in,char cs,float fs)" << endl;
    }
    ~Graduate()
    {
        cout << "~Graduate()" << endl;
    }
    Graduate(const Graduate& another):Student(another)
    {
        salary = another.salary;
    }
    void display()
    {
        print();
        cout<<salary<<endl;
    }
private:
    int salary;
};

int main(int argc, char *argv[])
{
    Graduate s("bauer", 1001,'M',8000);
    s.display();
    Graduate g = s;
    g.display();

    return 0;
}


4、派生类的赋值运算符重载


派生类的赋值操作符重载函数的定义如下:


子类& 子类::operator=(const 子类& another)
{
    if(this != &another)
{
  父类::operator =(another); // 调用父类的赋值运算符重载
    this->salary = another.salary;//子类成员初始化
}
        return * this;
}


派生类的如果没有实现赋值操作符函数,C++编译器会提供一个默认赋值操作符重载函数,默认的赋值操作符重载函数会调用父类的赋值操作符重载函数(编译器提供的默认赋值操作符重载函数或是开发者提供的赋值操作符重载函数)。


#include
#include

using namespace std;

class Student
{
public:
    Student(string sn,int n,char s)
    {
        name = sn;
        num = n;
        sex = s;
       cout <&l    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程