C++中继承(inheritance)详解及其作用介绍

概述

面向对象程序设计中最重要的一个概念是继承 (inheritance). 继承允许我们依据另一个类来定义一个类, 这使得创建和维护一个应用程序变得更统一. 这样做也达到了重用代码功能和提高执行效率的效果.

类的概念

一个类中包含了若干数据成员和成员函数. 不同的类中的数据成员和成员函数各不相同. 但是有时两个类的内容基本相同. 例如:

继承的概念

继承 (inheritance) 就是在一个已存在的类的基础上建立一个新的类.

  • 已存在的类: 基类 (base class) 或父类 (father class)
  • 新建立的类: 派生类 (derived class) 或子类 (son class)

一个新类从已有的类获得其已有特性, 称为类的继承.

  • 通过继承, 一个新建的子类从已有的父类那里获得父类的特性
  • 派生类继承了基类的所有数据成员和成员函数, 并可以对成员做必要的增加或调整

从已有的类 (父类) 产生一个新的子类, 称为类的派生.

  • 类的继承是用已有的类来建立专用新类的编程技术
  • 一个基类可以派生出多个派生类, 每一个派生类又可以作为基类再派生出新的派生类. 因此基类和派生类是相对而言的
  • 派生类是基类的具体化, 而基类则是派生类的抽象

单继承

单继承 (single inheritance) 指一个派生类只从一个基类派生.

  • 单继承关系形成的层次是一个树形结构
  • 箭头表示继承的方向, 从派生类指向基类

多重继承

多重继承 (multiple inheritance) 是指一个派生类有两个或多个基类. 派生类不仅可以从一个基类派生, 也可以从多个基类派生.

派生类

派生类的声明方式:

class 派生类名:[继承方式]基类名{
    派生类新增加的成员
};

成员访问限定符 (默认 private):

  • public (公用的)
  • private (私有的)
  • protected (受保护的)

继承方式包括 (默认 private):

  • public (公用的)
  • private (私有的)
  • protected (受保护的)

Student 类:

#ifndef PROJECT5_STUDENT_H
#define PROJECT5_STUDENT_H

#include <string>
using namespace std;

class Student {
protected:
    int number;
    string name;
    char sex;
public:
    Student(int num, string n, char s);
    void show();
};

#endif //PROJECT5_STUDENT_H

Student.cpp:

#include <iostream>
#include "Student.h"
using namespace std;

Student::Student(int num, string n, char s) {
    number = num;
    name = n;
    sex = s;
}

void Student::show() {
    cout << "number: " << number << endl;
    cout << "name: " << name << endl;
    cout << "sex: " << sex << endl;
}

Student 派生类:

#ifndef PROJECT5_STUDENT1_H
#define PROJECT5_STUDENT1_H

#include "Student.h"

class Student1:public Student {
private:
    int age;
    string address;
public:
    Student1(int num, string n, char s, int a, string addr);
    void show1();
};

#endif //PROJECT5_STUDENT1_H

Student1.cpp:

#include <iostream>
#include "Student1.h"
using namespace std;

Student1::Student1(int num, string n, char s, int a, string addr) : Student(num, n, s) {
    Student(num, n, s);
    age = a;
    address = addr;
}

void Student1::show1() {
    show();
    cout << "age: " << age << endl;
    cout << "address: " << address << endl;
}

mian:

#include <iostream>
#include "Student1.h"

int main() {
    Student1 student1(1, "Little White", 'f', 18, "火星");
    student1.show1();

    return 0;
}

输出结果:

number: 1
name: Little White
sex: f
age: 18
address: 火星

派生类中的成员包括从基类继承过来的成员和自己增加的成员两大部分. 每一部分布分别包括数据成员和成员函数.

派生类的构造函数和析构函数

构造函数和析构函数:

构造函数的主要作用是对数据成员初始化析构函数在释放对象前做一些相关的处理

因为派生类还继承了基类的数据成员. 设计派生类的构造函数时, 不仅要考虑派生类所增加的数据成员的初始化, 还应当考虑基类的数据成员初始化. 于是我们在执行派生类的构造函数时, 调用基类的构造函数.

派生类构造函数一般形式

派生类构造函数名 (总形式参数表列) : 基类构造函数名 (实际参数表列) {
    派生类中新增数据成员初始化语句
}

类内定义

在类内定义派生类构造函数:

Student1::Student1(int num, string n, char s, int a, string addr) : Student(num, n, s), age(a), address(addr) {}

类外定义

在类的外面定义派生类构造函数:

类内:
Student1(int num, string n, char s, int a, string addr);

类外:
Student1::Student1(int num, string n, char s, int a, string addr) : Student(num, n, s) {
    Student(num, n, s);  // 基类
    age = a;
    address = addr;
}

构造函数和析构函数执行的顺序

建立派生类对象时, 执行构造函数的顺序:

  • 派生类构造函数先调用基类构造函数
  • 再执行派生类构造函数本身 (即派生类构造函数的函数体)

在派生类对象释放时:

  • 先执行派生类析构函数 ~Derived()
  • 再执行其基类析构函数 ~Base()

Base 类:

#ifndef PROJECT5_BASE_H
#define PROJECT5_BASE_H

class Base {
protected:
    Base();
    ~Base();
};

#endif //PROJECT5_BASE_H

Base.cpp:

#include <iostream>
#include "Base.h"
using namespace std;

Base::Base() {
    cout << "基类构造" << endl;
}

Base::~Base() {
    cout << "基类析构" << endl;
}

Derived 类:

#ifndef PROJECT5_DERIVED_H
#define PROJECT5_DERIVED_H

#include "Base.h"
using namespace std;

class Derived: public Base{
public:
    Derived(char c);
    ~Derived();
};

#endif //PROJECT5_DERIVED_H

Derived.cpp:

#include <iostream>
#include "Derived.h"
using namespace std;

Derived::Derived(char c) {
    cout << "子类构造函数, 值:" << c << endl;
}

Derived::~Derived() {
    cout << "子类析构函数" << endl;
}

main:

#include <iostream>
#include "Derived.h"
using namespace std;

Derived::Derived(char c) {
    cout << "子类构造函数, 值:" << c << endl;
}

Derived::~Derived() {
    cout << "子类析构函数" << endl;
}

输出结果:

基类构造
子类构造函数, 值:b
子类析构函数
基类析构

子对象派生

子对象 (sub object), 即对象中的对象. 类的数据成员是另一个类的对象.

Student1 类:

#ifndef PROJECT5_STUDENT1_H
#define PROJECT5_STUDENT1_H

#include "Student.h"

class Student1:public Student {
private:
    int age;
    string address;
    Student president;
public:
    Student1(int num, string n, char s, int p_num, string p_n, char p_s, int a, string addr);
    void show1();
};

#endif //PROJECT5_STUDENT1_H

Student1.cpp:

#include <iostream>
#include "Student1.h"
using namespace std;

Student1::Student1(int num, string n, char s, int p_num, string p_n, char p_s, int a, string addr) : Student(num, n, s), president(p_num, p_n, p_s) {
    age = a;
    address = addr;
}

void Student1::show1() {
    show();
    cout << "age: " << age << endl;
    cout << "address: " << address << endl;
    cout << "==========班长信息==========" << endl;
    president.show();
}

main:

#include <iostream>
#include "Student1.h"
using namespace std;

int main() {
    Student1 student1(1, "Little White", 'f', 2, "班长", 'm', 18, "火星");
    student1.show1();

    return 0;
}

输出结果:

number: 1
name: Little White
sex: f
age: 18
address: 火星
==========班长信息==========
number: 2
name: 班长
sex: m

注意事项

  • 当不需要对派生类新增的成员函数进行任何初始化操作时, 派生类构造函数体可以为空
  • 基类没有构造函数或构造函数参数为空, 在派生类构造函数中可不写调用基类构造函数的语句, 盗用派生类构造函数时系统会自动调用基类的默认构造函数
  • 基类中定义了有参的构造函数, 派生类构造函数总必须写出基类的构造函数及其参数
  • 基类中既定义无参数的构造函数,又重载了有参数的构造函数, 派生类构造函数中可以调用带参的基类构造函数, 也可以不调用基类的构造函数

到此这篇关于C++中继承(inheritance)详解及其作用介绍的文章就介绍到这了,更多相关C++继承内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅谈C++继承中的名字查找

    实例如下: #include<iostream> #include<string> using namespace std; class Base { public: void func() { cout << "func() in Base." << endl; } void func(int a) { cout << "func(int a) in Base." << endl; } voi

  • C++继承的定义与注意事项

    一.什么是继承? 1.1.概念 **继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类. 1.2.定义 下面我们看到Person是父类,也称作基类.Student是子类,也称作派生类 1.2.1.继承关系和访问限定符 1.2.2.继承基类成员访问方式的变化 // 实例演示三种继承关系下基类成员的各类型成员访问关系的变化 class Person { public : void Prin

  • C语言模式实现C++继承和多态的实例代码

    这个问题主要考察的是C和C++的区别,以及C++中继承和多态的概念. C和C++的区别 C语言是面向过程的语言,而C++是面向对象的过程. 什么是面向对象和面向过程? 面向过程就是分析解决问题的步骤,然后用函数把这些步骤一步一步的进行实现,在使用的时候进行一一调用就行了,注重的是对于过程的分析.面向对象则是把构成问题的事进行分成各个对象,建立对象的目的也不仅仅是完成这一个个步骤,而是描述各个问题在解决的过程中所发生的行为. 面向对象和面向过程的区别? 面向过程的设计方法采用函数来描述数据的操作,

  • C语言实现C++继承和多态的代码分享

    这个问题主要考察的是C和C++的区别,以及C++中继承和多态的概念. C和C++的区别 C语言是面向过程的语言,而C++是面向对象的过程. 什么是面向对象和面向过程? 面向过程就是分析解决问题的步骤,然后用函数把这些步骤一步一步的进行实现,在使用的时候进行一一调用就行了,注重的是对于过程的分析.面向对象则是把构成问题的事进行分成各个对象,建立对象的目的也不仅仅是完成这一个个步骤,而是描述各个问题在解决的过程中所发生的行为. 面向对象和面向过程的区别? 面向过程的设计方法采用函数来描述数据的操作,

  • 代码讲解C++继承和派生

    继承是是指一个对象直接使用另一对象的属性和方法. 继承的作用: 1.描述客观事物的层次结构 2.分类的方法进行分析和描述 3.复杂的系统层次化,提高代码的重用性 4.增强语言功能,提高软件开发效益 继承分为单继承,多继承 1.单继承:class 派生类名:访问方式 基类名{ 派生类成员} 说明: 1.派生类名由用户自己命名 2.访问方式:公有.私有.保护 3.基类名必须是程序一个已有的类 4.冒号:告诉系统,派生类从那个基类派生 5.派生类成员为:新定义的成员 2.单继承之共有继承 3.单继承之

  • C++继承中的访问控制实例分析

    本文较为深入的探讨了C++继承中的访问控制,对深入掌握C++面向对象程序设计是非常必要的.具体内容如下: 通常来说,我们认为一个类有两种不同的用户:普通用户 和 类的实现者.其中,普通用户编写的代码使用类的对象,这部分代码只能访问类的公有(接口)成员:实现者则负责编写类的成员和友元的代码,成员和友元既能访问类的公有部分,也能访问类的私有部分.如果进一步考虑继承的话就会出现第三种用户,即派生类.派生类可以访问基类的公有(public)成员和受保护(protected)成员,但不能访问基类的私有(p

  • C++中继承(inheritance)详解及其作用介绍

    概述 面向对象程序设计中最重要的一个概念是继承 (inheritance). 继承允许我们依据另一个类来定义一个类, 这使得创建和维护一个应用程序变得更统一. 这样做也达到了重用代码功能和提高执行效率的效果. 类的概念 一个类中包含了若干数据成员和成员函数. 不同的类中的数据成员和成员函数各不相同. 但是有时两个类的内容基本相同. 例如: 继承的概念 继承 (inheritance) 就是在一个已存在的类的基础上建立一个新的类. 已存在的类: 基类 (base class) 或父类 (fathe

  • C/C++ 中memset() 函数详解及其作用介绍

    memset 函数是内存赋值函数,用来给某一块内存空间进行赋值的: 包含在<string.h>头文件中,可以用它对一片内存空间逐字节进行初始化: 原型为 : void *memset(void *s, int v, size_t n); 这里s可以是数组名,也可以是指向某一内在空间的指针: v为要填充的值: n为要填充的字节数: 例子: struct data { char num[100]; char name[100]; int n; }; struct data a, b[10]; me

  • C/C++中字符串流详解及其作用介绍

    目录 概述 字符串流 理解字符串流 输出字符串对象 输入字符串流对象 输入输出字符串流对象 案例一 案例二 字符数组 vs 文件 总结 概述 文件流类和字符串流类都是 ostream, istream 和 iostream 类的派生类, 因此对它们的操作方法是基本相同的. 字符串流 文件流 字符串流 概念 文件流是以外存文件为输入输出对象的数据流 字符串流也 称为内存流, 以内存中用户定义的字符数组 (字符串) 为输入输出的对象 相关流类 ifstream, ofstream 和 fstream

  • C/C++中命名空间(namespace)详解及其作用介绍

    目录 概述 命名空间 命名空间的作用 自定义命名空间 命名空间成员的方法 案例 概述 命名空间 (namespace) 可以帮助我们区分不同库中相同名称的函数, 类, 变量等. 使用了命名空间即定义了上下文. 命名空间就是定义了一个范围. 命名空间 为了解决 C++ 标准库中的标识符与程序中的全局标识符之间以及不同库中的所有标识符之间的命名冲突. 标准 C++ 库的所有标识符都定义在一个名为 std 的命名空间中. 在程序中用到 C++ 标准库时, 使用 std 作为限定. 我们在写 "Hell

  • C/C++中数据类型转换详解及其作用介绍

    目录 概述 不同类型数据间的转换 隐式类型转换 强制类型转换 自己声明的类型转换 转换构造函数 类型转换函数 案例 应用 概述 在日常的开发中, 我们经常会用到数据类型转换, 所以我们要对数据类型转换有一定的了解. 不同类型数据间的转换 在 C++ 中, 某些标准类型的数据之间可以自动转换. 隐式类型转换 隐式类型转换: 由 C++ 编译系统自动完成的, 我们无需干预. 例如: int main() { int a = 6; a = a + 3.5; cout << a << en

  • C++中指针的详解及其作用介绍

    目录 概述 指向对象的指针 指向对象数据成员的指针 this 指针 this 指针的作用 this 指针的实现 概述 指针 (pointer) 是一个变量, 其指为另一个变量的地址. 即内存位置的直接地址. 指向对象的指针 在建立对象时, 编译系统会为每一个对象分配一定的存储空间, 以存放其成员. 我们可以定义一个指针变量, 用来存放对象的指针. 例如: Time time1; Time *p; // 定义指针, 格式: 类名 *对象指针名 p = &time1; // 将指针指向Time类对象

  • C++中友元的详解及其作用介绍

    目录 概述 友元 普通的友元函数 友元成员函数 友元类 总结 概述 类的友元函数 (friend) 是定义在类外部, 但是有权限访问类的所有私有 (private) 成员和保护 (protected) 成员. 友元 我们先来复习一下公有成员和私有成员的概念: 公有成员 (public) : 在类外可以访问 私有成员 (private): 只有本类中的函数可以访问 友元 (friend) 可以访问与其有好友关系的类中的私有成员 (有限制的共享). 友元包括友元函数和友元类: 友元函数: 如果在本类

  • C++中模板(Template)详解及其作用介绍

    目录 概述 函数模板 类模板 模板类外定义成员函数 类库模板 抽象和实例 概述 模板可以帮助我们提高代码的可用性, 可以帮助我们减少开发的代码量和工作量. 函数模板 函数模板 (Function Template) 是一个对函数功能框架的描述. 在具体执行时, 我们可以根据传递的实际参数决定其功能. 例如: int max(int a, int b, int c){ a = a > b ? a:b; a = a > c ? a:c; return a; } long max(long a, l

  • C++中运算符重载详解及其作用介绍

    目录 概述 函数重载 运算符重载 C++ 的运算符 重载运算符的规则 成员函数实现 Complex 加法 运算符重载的方法 多种实现方法 实现 operator+= 三种运算符重载函数 成员函数实现 友元函数实现 输出结果 重载单元运算符 例子 重载二元运算符 例子 重载 I/O 插入运算符 << 提取运算符 >> 总结 概述 运算符重载 (Operator Overloading) 函数重载 重载: 将同一名字重新赋予新的含义. 函数重载: 对一个函数赋予新的含义, 使之实现新功

  • C/C++中虚函数详解及其作用介绍

    目录 概述 使用方法 关联 静态关联 动态关联 案例1 未使用虚函数 使用虚拟类 案例2 总结 概述 虚函数 (virtual function) 指可以被子类继承和覆盖的函数. 使用方法 基类声明成员函数为虚函数的方法: virtual [类型] 函数名([参数表列]) 注: 在类外定义虚函数时, 不需再加 virtual. 虚函数的特点: 提高程序扩充性: 派生类根据需要可以进行函数覆盖 成员函数被声明为虚数后, 其派生类中覆盖函数自动称为虚函数 若虚函数在派生类中未重新定义, 则派生类简单

随机推荐