首页 > 编程语言 >C++基础(3)

C++基础(3)

时间:2023-10-29 20:22:36浏览次数:33  
标签:基类 Basic 函数 val 派生类 基础 C++ basic



类的继承

基类与派生类之间的构造行为

派生类可以调用基类的公共成员,但无法调用基类的私有成员。所以派生类无法直接初始化基类中的私有成员变量。在派生类中初始化基类的私有成员变量需要显式的调用基类的构造函数,并以委托构造的方式将其初始化。

// 基类头文件 basic.h
#ifndef __BASIC__
#define __BASIC__

class Basic
{
private:
    int basic_pri_val;
    void basicPriFuc() const;
public:
    Basic(int _pri_val, int _pub_val):basic_pri_val(_pri_val), basic_pub_val(_pub_val){}
    int basic_pub_val;
    void basicPubFuc() const;
    void showBasicPriVal() const;
};
#endif
// 基类源文件 basic.cpp
#include <iostream>
#include "basic.h"
using std::cout;
void Basic::basicPriFuc() const
{
    cout<< "Basic private function.\n";
}

void Basic::basicPubFuc() const
{
    cout<< "Baisc public function.\n";
}

void Basic::showBasicPriVal() const
{
    cout<< "Basic private value: "<< basic_pri_val<< '\n';
}
// 派生类头文件 derive.h
#ifndef __DERIVE__
#define __DERIVE__

#include "basic.h"

class Derive:public Basic   // 从 Basic 类派生
{
public:
    Derive(int _basic_pri_val, int _basic_pub_val):Basic(_basic_pri_val, _basic_pub_val){}  // 委托基类构造函数初始化基类成员变量
};

#endif
// 派生类源文件 derive.cpp
#include "derive.h"
// 主程序源文件 main.cpp
#include "derive.h"

int main()
{
    Derive derive = {1, 2};

    // derive.basicPriFuc();    // 不可访问基类私有成员函数
    derive.basicPubFuc();       // 可以访问基类公共成员函数
    // derive.basic_pri_val;    // 不可访问基类私有成员变量
    derive.showBasicPriVal();   // 基类私有成员变量可以通过基类公共成员函数访问
    derive.basic_pub_val;       // 可以访问基类公共成员变量

    return 0;
}

Baisc public function.
Basic private value: 1

另外,基类的引用或指针可以指向派生类,但这样的引用和指针只能调用来自于基类的方法。

在派生类中使用基类方法

在派生类中使用基类方法只需要在方法前加上域解析运算符,如下:

// 假定类 Basic 中已经定义了 myPrint 方法
class Derive:: public Basic
{
public:
    void myPrint()
    {
        Basic::myPrint();   // 调用类 Basic 中的 myPrint 方法
        myPrint();          // 调用类 Derive 中的 myPrint 方法
    }
}

protected 的访问权限

对于类外而言,protected 的访问权限与 private 相似。对于派生类而言, protected 的访问权限与 public 相似。

多态公有继承

在进行本节之前需要知道:父类的指针/引用可以指向/引用派生类,但只能调用继承于父类的方法或重写在子类中的虚方法。

多态有静态多态和动态多态两个部分。

  • 静态多态相当于在派生类中重写了(不是重载)父类中的函数,函数的声明中,形参类型和数量可以与父类不一致。派生类只能调用重写后的函数,而不能够再使用被重写的父类中的函数。
  • 动态多态发生在使用父类指针或引用,调用或重写修函数时。下面将进行详细的演示。

关键字 virtual

  • 只有类的非静态成员函数可以成为虚函数,其他非类成员函数或类的静态成员函数不行。
  • 类中的虚函数,即使不被调用也必须被定义。而非虚函数在不被调用的情况下可以只声明不定义。
  • 派生类与父类中的虚函数声明必须完全一致,包括函数名与形参类型。
  • virtual 还可用于类的虚继承。

使用 virtual 修饰类的成员函数,其成员函数的调用行为只在下列情况下不同:

  • 对于一般的成员函数,如果使用类的指针或者引用来调用该函数,则函数的行为将取决于声明该指针/引用的类型。即如果是父类类型的的指针/引用,则将调用父类中的函数;如果是派生类类型的指针/引用,则将调用派生类中的函数。
  • 对于虚成员函数,如果使用类的指针或引用来调用该函数,则函数的行为取决于指针所指向的对象的类型。

示例

// 基类头文件 basic.h
#ifndef __BASIC__
#define __BASIC__

class Basic
{
private:
    int basic_pri_val;
    void basicPriFuc() const;
public:
    Basic(int _pri_val, int _pub_val):basic_pri_val(_pri_val), basic_pub_val(_pub_val){}
    // virtual ~Basic() {}; // 在包含虚函数时,应当包含一个虚析构函数
    int basic_pub_val;
    void basicPubFuc() const;
    void showBasicPriVal() const;

    void myPrint() const;   // 非虚函数,下面将在派生类中重写
};
#endif
// 基类源文件 basic.cpp
#include <iostream>
#include "basic.h"
using std::cout;
void Basic::basicPriFuc() const
{
    cout<< "Basic private function.\n";
}

void Basic::basicPubFuc() const
{
    cout<< "Baisc public function.\n";
}

void Basic::showBasicPriVal() const
{
    cout<< "Basic private value: "<< basic_pri_val<< '\n';
}

void Basic::myPrint() const
{
    cout<< "Basic class print.\n";
}
// 派生类头文件 derive.h
#ifndef __DERIVE__
#define __DERIVE__

#include "basic.h"

class Derive:public Basic   // 从 Basic 类派生
{
public:
    Derive(int _basic_pri_val, int _basic_pub_val):Basic(_basic_pri_val, _basic_pub_val){}   // 委托基类构造函数初始化基类成员变量

    void myPrint();     // 重写父类中的非虚函数

};

#endif
// 派生类源文件 derive.cpp
#include "derive.h"
using std::cout;
void Derive::myPrint() const
{
    cout<< "Derive class print.\n";
}
// 主程序源文件 main.cpp
#include "derive.h"

int main()
{
    Derive derive = {1, 2};
    Basic & basic = derive;
    basic.myPrint();

    return 0;
}

Basic class print.

当重写父类中的普通函数时,即使父类引用引用了派生类,但是该引用调用的却是父类中的函数。myPrint 函数的行为却决于引用类型。

如果我们在声明中为 myPrint() 函数加上 virtual 修饰,则程序结果为:

Derive class print

可以看到,myPrint() 函数的行为取决于引用所指向的类。

如果需要在派生类中重定义基类中的方法,则应尽量将该方法声明为虚。且需要在基类中声明一个虚析构函数。

当类被用作基类时,它的虚构函数应当被设置为虚函数,否则将会对派生类对象的内存释放造成麻烦。

抽象基类(ABC)

类中包含纯虚函数的类被称为抽象基类。纯虚函数的声明如下:

class ABC
{
public:
    virtual void myPrint() const = 0;
}

纯虚函数可以在抽象基类中被定义。抽象基类的派生类必须使用重写虚函数的方法来重写纯虚函数。抽象基类强制派生类实现其纯虚函数。

私有继承和保护继承

  • 在私有继承中,基类的公有成员和保护成员都将成为派生类的私有成员。
  • 在保护继承中,基类的公有成员和保护成员都将成为派生类的保护成员。

多重继承

class Deriver : public Basic1, private Basic2 {···};

标签:基类,Basic,函数,val,派生类,基础,C++,basic
From: https://www.cnblogs.com/torch-hxm/p/17796367.html

相关文章

  • 2023-2024-1 20231421 《计算机基础与程序设计》第五周学习总结
    ------------恢复内容开始------------------------恢复内容开始------------作业信息作业要求:https://www.cnblogs.com/rocedu/p/9577842.html#WEEK05作业目标:自学《计算机科学概论》第六章、《c语言程序设计》第四章作业正文:教材学习内容总结一、《计算机科学概论》第六......
  • 2023-2024-1 20231307 《计算机基础与程序设计》第5周学习总结
    2023-2024-120231307《计算机基础与程序设计》第5周学习总结作业信息这个作业属于哪个课程<班级的链接>(如2023-2024-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(如2023-2024-1计算机基础与程序设计第5周作业)这个作业的目标<计算机科学概论第6章......
  • # 学期2023-2024-1 20231401 《计算机基础与程序设计》第五周学习总结
    学期2023-2024-120231401《计算机基础与程序设计》第五周学习总结作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2023-2024-1计算机基础与程序设计第五周作业这个作业的目标自学教材:计算机科学概论第6章,C语言程序设计第4章并......
  • 互联网的一些基础知识
    IP地址网络的本质其实就是不同终端之间的数据交换。而IP地址就是互联网给每一台终端分配的逻辑地址,我们可以把“个人计算机”比作“一台电话”,那么“IP地址”就相当于“电话号码”。IPV4和IPV6目前采用比较多的ip地址规范是ipv4,ipv4格式的ip地址是一个32位的二进制数,通常被分割......
  • Java 基础学习第一弹
    1.equels和==的区别equals方法用于比较对象的内容是否相等,可以根据自定义的逻辑来定义相等的条件,而==操作符用于比较对象的引用是否相等,即它们是否指向同一块内存地址。equals方法是一个实例方法,可以被所有的Java对象调用,而==操作符可以用于比较对象的引用或基本数据类型的......
  • 2023-2024-1 20231417 《计算机基础与程序设计》第五周学习总结
    2023-2024-120231417《计算机基础与程序设计》第五周学习总结作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2023-2024-1计算机基础与程序设计第五周作业这个作业的目标<关于机器语言与汇编语言,pep9的相关应用,循坏算法的了解与......
  • 【基础算法】递归
    一、递归是什么递归是一种应用非常广泛的算法(或者变成技巧),很多算法的实现都需要依赖递归,比如,归并排序、快速排序、DFS深度优先搜索、二叉树的前中后序遍历等。所以,搞懂递归非常重要。简单来说,递归就是在函数中调用自己。递归求解问题分为“递”和“归”2个过程。 我们通过......
  • 简单c++构建第一人称
    本文内容为UE4.27的文档教程GameMode确定新建的项目会自动生成GameMode,如果有更改,而不是使用默认的GameMode类,就需要在引擎的设置中更改角色的实现前后左右移动//前后MoveForwardvoidAFPSCharacter::MoveForward(floatvalue){ //利用控制器方向寻找前进的方向就是角色......
  • C++多线程编程——线程的基本概念和使用方法
    什么是线程?在计算机科学中,线程是进程中的一个执行控制单元,也被称为执行路径。每个进程可以包含多个线程,每条线程并行执行不同的任务。线程是操作系统可识别的最小执行和调度单位。进程和线程的区别进程是程序在某个数据集合上的一次运行活动,也是操作系统进行资源分配和保护的......
  • Java基础语法
    一、注释:1、什么是注释:注释是写在程序中对代码进行解释说明的文字,方便自己和其他人查看,以便于理解程序。2、注释有哪些:a:单行注释://   注释内容只可写一行  (快捷键:ctrl+/) b:多行注释:   /**/       /*  注释内容1             ......