C++继承:构建类层级结构的关键技术

一、继承的基本概念

继承是面向对象程序设计的基本特征之一。在C++语言中,继承允许我们定义一个新的类,这个新类继承已有的类的属性和行为,从而可以重复使用已有类的代码,避免代码冗余。

在C++中,通过在类定义中使用“:”符号,来指定一个类从另一个类继承而来。被继承的类称为基类,新定义的类称为派生类。派生类可以继承基类的公有成员、保护成员和私有成员,但只有公有成员能够被外部程序访问。

class BaseClass {
public:
    void publicFunc() { //公有函数
        std::cout << "BaseClass 的 publicFunc() 函数" << std::endl;
    }
protected:
    void protectedFunc() { // 保护函数
        std::cout << "BaseClass 的 protectedFunc() 函数" << std::endl;
    }
private:
    void privateFunc() { // 私有函数
        std::cout << "BaseClass 的 privateFunc() 函数" << std::endl;
    }
};

class DerivedClass : public BaseClass {
public:
    void callPublicFunc() {
        publicFunc(); // 从基类继承的公有函数
    }
    void callProtectedFunc() {
        protectedFunc(); // 从基类继承的保护函数
    }
   //void callPrivateFunc() { privateFunc(); }; 该语句会编译错误
};

int main() {
    DerivedClass obj; 
    obj.callPublicFunc(); //调用从基类继承而来的公有成员函数
    obj.callProtectedFunc(); //调用从基类继承而来的保护成员函数
    //obj.callPrivateFunc(); //编译错误,私有成员函数不能被访问
    return 0;
}

二、继承类型

在C++中,继承被分为三类:公有继承、保护继承和私有继承。

1.公有继承

公有继承是最常用的继承方式,它指定派生类能够继承基类的公有成员和保护成员。在公有继承中,基类的公有成员和保护成员在派生类中的访问权限不变。

class BaseClass {
public:
    void publicFunc() { 
        std::cout << "BaseClass 的公有函数" << std::endl;
    }
protected:
    void protectedFunc() { 
        std::cout << "BaseClass 的保护函数" << std::endl;
    }
};

class DerivedClass : public BaseClass {
    //从基类继承而来的公有成员和保护成员在DerivedClass中的访问权限不变
};

int main() {
    DerivedClass obj; 
    obj.publicFunc(); //从基类继承而来的公有成员函数可以在外部程序中被访问
    //obj.protectedFunc(); 非法,派生类外不能访问基类的保护成员
    return 0;
}

2.保护继承

保护继承与公有继承类似,不同之处在于基类的公有成员和保护成员在派生类中都成为保护成员,在派生类外部不能访问。只有派生类的成员函数或友元函数能够访问它们。

class BaseClass {
public:
    void publicFunc() { 
        std::cout << "BaseClass 的公有函数" << std::endl;
    }
protected:
    void protectedFunc() { 
        std::cout << "BaseClass 的保护函数" << std::endl;
    }
};

class DerivedClass : protected BaseClass {
    //从基类继承而来的公有成员和保护成员在DerivedClass中成为保护成员,其他程序不能访问
public:
    void callProtectedFunc() {
        protectedFunc(); //从基类继承而来的保护函数可以在派生类中被访问
    }
};

int main() {
    DerivedClass obj; 
    //obj.publicFunc(); 非法,从基类继承而来的公有成员在派生类外部不能访问
    //obj.protectedFunc(); 非法,从基类继承而来的保护成员在派生类外部不能访问
    obj.callProtectedFunc(); //从基类继承而来的保护函数可以在派生类中被访问
    return 0;
}

3.私有继承

私有继承意味着基类的公有和保护成员在派生类中均成为私有成员,只有派生类的成员函数或友元函数能够访问它们。私有继承不会带来新的接口。

class BaseClass {
public:
    void publicFunc() { 
        std::cout << "BaseClass 的公有函数" << std::endl;
    }
protected:
    void protectedFunc() { 
        std::cout << "BaseClass 的保护函数" << std::endl;
    }
};

class DerivedClass : private BaseClass {
    //从基类继承而来的公有成员和保护成员在DerivedClass中均为私有成员
public:
    void callProtectedFunc() {
        protectedFunc(); //从基类继承而来的保护函数可以在派生类中被访问
    }
};

int main() {
    DerivedClass obj; 
    //obj.publicFunc(); 非法,从基类继承而来的公有成员在派生类外部不能访问
    //obj.protectedFunc(); 非法,从基类继承而来的保护成员在派生类外部不能访问
    obj.callProtectedFunc(); //从基类继承而来的保护函数可以在派生类中被访问
    return 0;
}

三、构造函数和析构函数中的继承

在进行继承时,基类的构造函数和析构函数会被自动调用。

在构造派生类的对象时,首先会调用基类的默认构造函数,然后调用派生类的构造函数。当然,也可以在派生类的构造函数中显式调用基类的构造函数。考虑以下代码:

class BaseClass {
public:
    BaseClass() { //基类的默认构造函数
        std::cout << "BaseClass 的构造函数" << std::endl;
    }
    ~BaseClass() { //基类的析构函数
        std::cout << "BaseClass 的析构函数" << std::endl;
    }
};

class DerivedClass : public BaseClass {
public:
    DerivedClass() { //派生类的构造函数
        std::cout << "DerivedClass 的构造函数" << std::endl;
    }
    ~DerivedClass() { //派生类的析构函数
        std::cout << "DerivedClass 的析构函数" << std::endl;
    }
};

int main() {
    DerivedClass obj; //创建一个派生类的对象
    return 0;
}

执行上述代码,将输出以下结果:

BaseClass 的构造函数
DerivedClass 的构造函数
DerivedClass 的析构函数
BaseClass 的析构函数

在析构派生类的对象时,先调用派生类的析构函数,然后调用基类的析构函数。同样,也可以在派生类的析构函数中显式调用基类的析构函数。

四、虚函数和多态

虚函数是C++用于实现多态的重要机制。在基类中声明一个虚函数,派生类可以根据其需求重新定义这个虚函数,以实现多态性。在调用虚函数时,函数的实际调用取决于对象的类型,而不是指向该对象的指针或引用类型。例如:

class BaseClass {
public:
    virtual void virtualFunc() { 
        std::cout << "BaseClass 的虚函数" << std::endl;
    }
};

class DerivedClass : public BaseClass {
public:
    void virtualFunc() { //重定义基类的虚函数
        std::cout << "DerivedClass 的虚函数" << std::endl;
    }
};

int main() {
    DerivedClass obj; //创建一个派生类的对象
    BaseClass& ref = obj; //使用基类的引用来引用派生类的对象
    ref.virtualFunc(); //调用“引用的对象”的虚函数
    return 0;
}

以上代码中,我们声明了一个基类和一个派生类,基类中的虚函数被派生类重定义,使得它们的实现不同。在main函数中,创建了一个派生类对象,并用基类的引用来引用该对象,最后调用了该对象的虚函数。由于虚函数是根据对象类型而不是引用类型确定的,因此程序将调用派生类的虚函数,输出以下内容:

DerivedClass 的虚函数

五、抽象类

抽象类是具有至少一个纯虚函数的类,不能直接实例化,只能作为其他类的基类使用。纯虚函数没有函数体,只有函数原型。在基类中声明纯虚函数后,在派生类中必须定义该函数,否则将编译错误。

class AbstractClass { //抽象类
public:
    virtual void pureVirtualFunc() = 0; //纯虚函数
};

class DerivedClass : public AbstractClass {
public:
    void pureVirtualFunc() { 
        std::cout << "DerivedClass 实现了纯虚函数 pureVirtualFunc()" << std::endl;
    }
};

int main() {
    //AbstractClass obj; 非法,抽象类不能直接实例化
    DerivedClass obj; //创建一个派生类的对象
    AbstractClass& ref = obj; //使用基类的引用来引用派生类的对象
    ref.pureVirtualFunc(); //调用“引用的对象”的纯虚函数
    return 0;
}

在以上示例中,AbstractClass 是一个抽象类,定义了一个纯虚函数。派生类DerivedClass 定义了纯虚函数 pureVirtualFunc() 的实现,使得该派生类不再是抽象类。最后,创建了一个DerivedClass 对象,并用基类的引用来引用它,并调用了该对象的纯虚函数。

六、总结

在C++中,继承是构建类层级结构的关键技术之一。通过继承,我们可以重用已有的类的代码,提高程序的可维护性和可扩展性。C++中的继承有三种类型:公有继承、保护继承和私有继承。

C++中的构造函数和析构函数在进行继承时,会自动调用。虚函数和多态则是C++实现动态多态的重要机制。抽象类不能直接实例化,必须作为其他类的基类使用。

了解和掌握C++中的继承及相关特性,有助于我们构建更加复杂的类层级结构,提高

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/256550.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-15 12:41
下一篇 2024-12-15 12:41

相关推荐

  • Vue TS工程结构用法介绍

    在本篇文章中,我们将从多个方面对Vue TS工程结构进行详细的阐述,涵盖文件结构、路由配置、组件间通讯、状态管理等内容,并给出对应的代码示例。 一、文件结构 一个好的文件结构可以极…

    编程 2025-04-29
  • Python程序的三种基本控制结构

    控制结构是编程语言中非常重要的一部分,它们指导着程序如何在不同的情况下执行相应的指令。Python作为一种高级编程语言,也拥有三种基本的控制结构:顺序结构、选择结构和循环结构。 一…

    编程 2025-04-29
  • Lidar避障与AI结构光避障哪个更好?

    简单回答:Lidar避障适用于需要高精度避障的场景,而AI结构光避障更适用于需要快速响应的场景。 一、Lidar避障 Lidar,即激光雷达,通过激光束扫描环境获取点云数据,从而实…

    编程 2025-04-27
  • Switch C:多选结构的利器

    在编写程序时,我们经常需要根据某些条件执行不同的代码,这时就需要使用选择结构。在C语言中,有if语句、switch语句等多种选择结构可供使用。其中,switch语句是一种非常强大的…

    编程 2025-04-25
  • Python分支结构的详细阐述

    一、if语句的基本语法 if 条件: 代码语句1 代码语句2 …… if语句是Python分支结构中最基本也是最常用的结构,它的基本语法如上所示。if语句会先判断条件是否成立,如果…

    编程 2025-04-24
  • 深入理解 Vue 目录结构

    Vue 是一款由 Evan You 开发的流行 JavaScript 框架。Vue 具有响应式视图和组件化的思想,让开发者可以轻松构建交互式的 Web 应用。那么在 Vue 开发中…

    编程 2025-04-24
  • JS递归遍历树结构详解

    一、JS递归遍历树结构并修改 function traverse(node) { if(node == null) return; //遍历结束 node.value++; // …

    编程 2025-04-24
  • 详解数组结构

    一、数组的基本概念 数组是一种有序的数据结构,可以容纳一组相同数据类型的元素。每个元素有一个唯一的索引(下标),可以通过下标来访问数组的元素。数组一般分为一维和多维,也可以具有不同…

    编程 2025-04-23
  • 残差结构:从原理到应用

    一、残差结构的原理 残差结构在深度学习中的应用越来越广泛,其核心原理是将输入特征和参考特征拼接在一起进行训练,以增强模型的学习能力和泛化能力。 具体地,残差结构引入了跨层连接,使得…

    编程 2025-04-23
  • LTE帧结构详解

    一、帧结构简介 LTE网络中的帧结构是由多个子帧和时隙构成的。每个子帧由14个符号组成,符号的长度为0.5ms。每个符号中又包含7个资源块,一个资源块可以传输12个子载波。一个子帧…

    编程 2025-04-22

发表回复

登录后才能评论