【C++】面向对象编程的三大特性:深入解析继承机制(一)

本文涉及的产品
云解析DNS-重点域名监控,免费拨测 20万次(价值200元)
简介: 【C++】面向对象编程的三大特性:深入解析继承机制

一、前文

面向对象编程的三大特性:封装、继承和多态。

  1. 封装通过将数据和方法封装在对象中,提高了数据的安全性和代码的可维护性。
  2. 继承允许新类从现有类继承属性和方法,实现代码复用和扩展。
  3. 多态则通过统一的接口实现不同的行为,提高了代码的灵活性和扩展性。

封装:

  1. 数据和方法放到一起,把想给访问定义成公有,不想给你访问定义成私有和保护
  2. 一个类型放到另一个类型里面,通过typedef成员函数调整,封装另一个全新的类型相当于武器库

二、继承

2.1 继承概念

  • 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。
  • 它允许一个类(称为子类或派生类)从另一个类(称为父类或基类)继承属性和方法
  • 每个派生类对象都是一个特殊的基类对象,派生类在基类的基础上进行扩展,增加新功能
  • 继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。
  • 以前我们接触的复用都是函数复用,继承是类设计层次的复用
using namespace std;
class Person
{
    public:
    void Print()
    {
        cout << "name:" << _name << endl;
        cout << "age:" << _age << endl;
    }
    private:
    string _name = "peter";//名字
    int _age = 18;//年龄
};
class Student : public Person
{
    protected:
    int _stuid;//学号
};
class Teacher : public Person
{
    protected:
    int jobid;//工号
};
int main()
{
    Student s;
    Teacher t;
    s.Print();
    t.Print();
    return 0;
}

从代码中可以看出Person是父类或基类,Student是子类或派生类

2.2 继承关系和访问限定符

2.3 继承基类成员访问方式间变化

注意】:圈出来的是实践中最常见的设计方式,主要了解这部分。

2.4 基类的private成员

基类private成员在派生类中无论以什么方式继承都是不可见的,这里的不可见是指基类的私有成员还是被继承到了派生类中,但是语法上限制派生类对象不管在类里面还是在类外面都是不能去访问

class Person
{
    public:
    void Print()
    {
        cout << "name:" << _name << endl;
        cout << "age:" << _age << endl;
    }
    protected:
    string _name = "peter";
    private:
    int _age = 18;
};
class Student : public Person
{
    public:
    void func()
    {
        cout << _name << endl;
        cout << _age << endl;
    }
    protected:
    int _stuid;
};

按照上面的意思,Student继承了Person属性和方法,但是由于_age是属于私有成员是不可见且不能被访问。

2.4.1 公共接口间接使用基类的私有变量

class Student : public Person
{
    public:
    void func()
    {
        //间接的使用
        Print();
    }
    protected:
    int _stuid;
};

由于基类private成员在派生类中式不能被访问的,如果基类成员不想在类外直接被访问,但是需要在派生类中能访问。这样子可以将基类private成员定义为protected成员,可以看出来保护成员限定符是因继承才出现的

思考:

  • 类可以使用关键字class或者struct,他们只是默认的继承方式不同,为什么不使用struct呢?

解释:

  • struct默认继承方式和访问限定符都是公有的
  • class默认继承方式和访问限定符都是私有的
  • 最好函数显式写出继承方式,偷偷摸摸的不好!

2.5小结

  • 基类的私有成员在子类都是不可见。基类的其他成员在访问方式(取最小的权限)== Min(成员在基类的访问限定符、继承方式)public > prrotected > private
  • 在实际中一般常用的是public继承,而不是protected/private继承,也不提倡使用protected/private继承,因为protected/private继承下来的成员都是只能在派生类的类里面使用,实际中扩展维护性不强

2.6 基类和派生类对象赋值转换

2.6.1 派生类赋值基类

每个派生类对象都是一个特殊的基类对象,派生类在基类的基础上进行扩展,增加新功能

class Person
{
    protected:
    string _name;
    string _sex;
    int _age;
};
class Student : public Person
{
    public:
    int _No; //学号
};

派生类对象可以赋值基类的对象/基类的指针/基类的引用。这里有个形象的说法叫切片或者切割。(将派生类中父类那部分切来赋值过去)。

int main()
{
    Student sobj;
  //子类对象可以赋值给父类对象
    Person pobj = sobj;
    //子类对象可以赋值给父类指针
    Person* pp = &sobj;
    //子类对象可以赋值给父类引用
    Person& rp = sobj;
}

2.6.2 基类对象不能赋值给派生类对象(建立在public继承)

int main()
{
    Student sobj;
    Person pobj = sobj;
    Person* pp = &sobj;
    sobj = pobj;
}

基类是不能直接赋值给派生类,因为可能派生类包含了基类没有的额外属性和方式,而且基类是不具备这些属性和方式,对此不能直接赋值。

2.6.3 强制基类赋值派生类

基类的指针或者引用可用通过强制类型转化赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。

int main()
{
    Student sobj;
    Person pobj = sobj;
    Person* pp = &sobj;
    1.0
    //pp存放这子类实例的地址,再进行强转
    pp = &sobj; 
    // 这种情况转换时可以的。
    Student* ps1 = (Student*)pp; 
    ps1->_No = 10;
  
    2.0
    //pp存放父类实例的地址
    pp = &pobj;
    // 这种情况转换时虽然可以,但是会存在越界访问的问题
    Student* ps2 = (Student*)pp; 
    ps2->_No = 10;
}

注意:

  • 以上提前需要满足是公有继承
  • 切割/切片是赋值兼容,编译器进行特殊处理,不产生临时对象,将子拷贝给父。内置类型值拷贝,自定义类型调用拷贝构造。


【C++】面向对象编程的三大特性:深入解析继承机制(二)https://developer.aliyun.com/article/1617389

相关文章
|
10月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
8月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
308 12
|
8月前
|
存储 监控 算法
基于 C++ 哈希表算法的局域网如何监控电脑技术解析
当代数字化办公与生活环境中,局域网的广泛应用极大地提升了信息交互的效率与便捷性。然而,出于网络安全管理、资源合理分配以及合规性要求等多方面的考量,对局域网内计算机进行有效监控成为一项至关重要的任务。实现局域网内计算机监控,涉及多种数据结构与算法的运用。本文聚焦于 C++ 编程语言中的哈希表算法,深入探讨其在局域网计算机监控场景中的应用,并通过详尽的代码示例进行阐释。
171 4
|
12月前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
10月前
|
安全 编译器 C语言
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
|
10月前
|
存储 程序员 C语言
【C++篇】深度解析类与对象(上)
在C++中,类和对象是面向对象编程的基础组成部分。通过类,程序员可以对现实世界的实体进行模拟和抽象。类的基本概念包括成员变量、成员函数、访问控制等。本篇博客将介绍C++类与对象的基础知识,为后续学习打下良好的基础。
|
12月前
|
安全 编译器 C++
C++ `noexcept` 关键字的深入解析
`noexcept` 关键字在 C++ 中用于指示函数不会抛出异常,有助于编译器优化和提高程序的可靠性。它可以减少代码大小、提高执行效率,并增强程序的稳定性和可预测性。`noexcept` 还可以影响函数重载和模板特化的决策。使用时需谨慎,确保函数确实不会抛出异常,否则可能导致程序崩溃。通过合理使用 `noexcept`,开发者可以编写出更高效、更可靠的 C++ 代码。
|
12月前
|
存储 程序员 C++
深入解析C++中的函数指针与`typedef`的妙用
本文深入解析了C++中的函数指针及其与`typedef`的结合使用。通过图示和代码示例,详细介绍了函数指针的基本概念、声明和使用方法,并展示了如何利用`typedef`简化复杂的函数指针声明,提升代码的可读性和可维护性。
|
编译器 PHP 开发者
PHP 8新特性解析与实战应用####
随着PHP 8的发布,这一经典编程语言迎来了诸多令人瞩目的新特性和性能优化。本文将深入探讨PHP 8中的几个关键新功能,包括命名参数、JIT编译器、新的字符串处理函数以及错误处理改进等。通过实际代码示例,展示如何在现有项目中有效利用这些新特性来提升代码的可读性、维护性和执行效率。无论你是PHP新手还是经验丰富的开发者,本文都将为你提供实用的技术洞察和最佳实践指导。 ####
227 1
|
数据安全/隐私保护 iOS开发 开发者
iOS 14隐私保护新特性深度解析####
随着数字时代的到来,隐私保护已成为全球用户最为关注的问题之一。苹果在最新的iOS 14系统中引入了一系列创新功能,旨在增强用户的隐私和数据安全。本文将深入探讨iOS 14中的几大隐私保护新特性,包括App跟踪透明度、剪贴板访问通知和智能防追踪功能,分析这些功能如何提升用户隐私保护,并评估它们对开发者和用户体验的影响。 ####

推荐镜像

更多
  • DNS