前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >封装、继承、多态、重载:C++中的强大特性与代码设计

封装、继承、多态、重载:C++中的强大特性与代码设计

作者头像
洁洁
发布于 2024-01-03 02:24:04
发布于 2024-01-03 02:24:04
60300
代码可运行
举报
文章被收录于专栏:小洁叫你mysql小洁叫你mysql
运行总次数:0
代码可运行
这里写目录标题
  • 封装
    • C语言封装风格
    • C++封装
  • 继承
  • 多态
    • 多态的实现
    • 虚函数概念:
    • 虚表指针
    • overload
    • overwrite
    • override
    • 抽象类
  • 重载

封装

C++中的封装是一种面向对象编程的概念,它将数据(成员变量)和操作(成员函数)封装在一个类中,通过访问控制来限制对类内部实现的访问。封装提供了类与外部世界之间的接口,隐藏了类的内部实现细节,提高了代码的可维护性和安全性。

在C++中,封装可以通过使用访问修饰符(public、private、protected)来实现:

public(公有)访问修饰符允许类的成员在类的外部被访问,也可以在类的内部被访问。通常将公有成员函数作为类的接口,供外部使用。 private(私有)访问修饰符将类的成员隐藏在类的内部,外部无法直接访问私有成员变量和私有成员函数。通常将私有成员用于实现类的内部逻辑。 protected(保护)访问修饰符与私有访问修饰符类似,但允许派生类(子类)访问基类中的保护成员。 下面是一个简单的封装示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyClass {
private:
    int privateData;  // 私有成员变量

public:
    void setPrivateData(int data) {  // 公有成员函数
        privateData = data;
    }

    int getPrivateData() const {  // 公有成员函数
        return privateData;
    }
};

int main() {
    MyClass obj;
    obj.setPrivateData(42);
    int data = obj.getPrivateData();
    return 0;
}

在上面的示例中,私有成员变量privateData被封装在类MyClass中,外部无法直接访问。通过公有成员函数setPrivateData和getPrivateData来操作私有成员变量。

封装可以提供更好的代码组织和管理方式,同时也增强了代码的安全性,因为外部代码无法直接修改和访问类的内部数据。

C语言封装风格

当单一变量无法完成描述需求的时候,结构体类型解决了这问题。可以将多个类型打包成一体,形成新的类型,这是c语言中封装的概念。但是,新类型并不包含对数据类的操作,所有操作都是通过函数的方式,去进行封装。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1 #include<iostream>
  2 #include<string>
  3 using namespace std;
  4 
  5 struct person
  6 {
  7     string name;
  8     int age;
  9     int height;
 10 };
 11 void init(person* p)
 12 {
 13     p->name = "jiejie";
 14     p->age = 20;
 15     p->height = 130;
 16 }
 17 void show(person p)
 18 {
 19     cout<<"p.name = "<<p.name<<endl;
 20     cout<<"p.age = "<<p.age<<endl;
 21     cout<<"p.height = "<<p.height<<endl;
 22 }
 23 int main()
 24 {
 25     person per;
 26     init(&per);
 27     show(per);
 28 
 29     return 0;
 30 }

把数据放到一起用struct包装,然后把数据以引用或指针的方式传给行为。

C++封装

C++的封装认为C语言的封装不彻底,对于数据和行为分类,没有权限控制。 C++则提供控制选择,将数据和行为放在一起,对内开放数据,逻辑抽象。对外提供接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1 #include<iostream>
  2 using namespace std;
  3 
  4 class person
  5 {   
  6     public: 
  7         int num;
  8         void init()
  9         {
 10             cin>>this->num;
 11             cin>>this->age;
 12             cin>>this->height;
 13         }
 14         void show()
 15         {
 16             cout<<num<<endl;
 17             cout<<age<<endl;
 18             cout<<height<<endl;
 19         }
 20     
 21     protected:
 22         int age;
 23     private:
 24         int height;
 25 };
 26 int main()
 27 {
 28     person p;
 29     p.init();
 30     p.show();
 31     return 0;
 32 }

基本流程: 通过创建一个类,再通过创建类对象 再由对象调用行为,完成需求。

继承

C++中的继承是面向对象编程的一个重要概念,它允许一个类(派生类/子类)从另一个类(基类/父类)继承属性和行为。继承可以通过创建一个新类并从基类派生来实现,新类将自动获得基类的成员变量和成员函数,同时可以添加新的成员或重写基类的成员函数。

继承的主要目的是实现代码的重用和构建类之间的层次关系。在继承关系中,基类被称为超类或父类,派生类被称为子类。 一般定义格式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class 派生类名标识符: [继承方式] 基类名标识符
{
[访问控制修饰符]
[成员声明列表]
};

继承方式有3种,分别为公有型,保护型和私有型,访问控制修饰符也是public,protected,private 类型。 成员声明列表中包含类成员变量以及成员函数,是派生类新增的成员。 “:”是一个运算符,表示基类和派生类之间的继承关系。

C++中的继承有以下几种类型:

公有继承(public inheritance):派生类继承了基类的公有成员和保护成员,并且这些成员在派生类中的访问权限与基类中的一样。派生类的对象可以直接访问基类的公有成员。

私有继承(private inheritance):派生类继承了基类的公有成员和保护成员,但是这些成员在派生类中的访问权限变为私有。派生类的对象不能直接访问基类的公有成员,只能通过派生类的成员函数来间接访问。

保护继承(protected inheritance):派生类继承了基类的公有成员和保护成员,但是这些成员在派生类中的访问权限变为保护。派生类的对象不能直接访问基类的公有成员,只能通过派生类的成员函数来间接访问。

在C++中,使用关键字class或struct来定义一个类,并使用关键字public、private或protected来指定成员的访问权限。

下面是一个简单的继承示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Shape {
public:
    void draw() {
        std::cout << "Drawing a shape" << std::endl;
    }
};

class Rectangle : public Shape {
public:
    void draw() {
        std::cout << "Drawing a rectangle" << std::endl;
    }
};

int main() {
    Shape shape;
    shape.draw();  // 输出:"Drawing a shape"

    Rectangle rectangle;
    rectangle.draw();  // 输出:"Drawing a rectangle"

    return 0;
}

在上面的示例中,Shape类是基类,它有一个公有成员函数draw。Rectangle类是派生类,通过public关键字继承了Shape类。Rectangle类重写了draw函数,实现了自己的绘制行为。在main函数中,我们分别创建了Shape对象和Rectangle对象,并调用了它们的draw函数。

继承是一种强大的代码复用工具,它可以使得类之间的关系更加清晰和有组织。通过继承,派生类可以继承基类的接口和实现,并且可以添加自己的功能或修改基类的行为。

继承是面对对象的主要特性之一,它使一个类可以从现有类中派生,而不必重新定义一个类。

实质:用已有的数据类型创建新的数据类型,并保留已有数据类型的特点,以旧类为基础创建新类,新类包含旧类的数据成员和成员函数。并且·可以在新类中添加新的数据成员和成员函数。 旧类被称为基类或者父类,新类被称为派生类或者子类。

多态

C++中的多态是面向对象编程的一个重要概念,它允许使用指针或引用来处理不同类型的对象,而实际上执行的是根据对象类型动态选择的相关操作。多态性可以提高代码的灵活性、可复用性和可扩展性。

C++中的多态性主要通过虚函数(virtual function)和运行时类型识别(runtime type identification)两个机制来实现:

虚函数:在基类中声明虚函数,并在派生类中进行重写。当通过指向基类的指针或引用调用虚函数时,将根据实际对象的类型来选择正确的函数实现。这种动态选择函数的机制称为动态绑定(dynamic binding)。虚函数通过关键字virtual进行声明。

运行时类型识别(RTTI):C++提供了dynamic_cast和typeid两个运算符来进行运行时类型识别。dynamic_cast用于将基类指针或引用转换为派生类指针或引用,如果转换成功,返回指向派生类的指针或引用;如果转换失败,则返回空指针或抛出bad_cast异常。typeid用于获取表达式的实际类型。

下面是一个简单的多态示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>

class Shape {
public:
    virtual void draw() {
        std::cout << "Drawing a shape" << std::endl;
    }
};

class Rectangle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a rectangle" << std::endl;
    }
};

class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a circle" << std::endl;
    }
};

int main() {
    Shape* shapePtr;

    Rectangle rectangle;
    Circle circle;

    shapePtr = &rectangle;
    shapePtr->draw();  // 输出:"Drawing a rectangle"

    shapePtr = &circle;
    shapePtr->draw();  // 输出:"Drawing a circle"

    return 0;
}

在上面的示例中,Shape类有一个虚函数draw,Rectangle和Circle类分别是派生自Shape的两个子类,并重写了draw函数。在main函数中,我们使用指向基类的指针shapePtr来处理不同类型的对象。通过将shapePtr指向Rectangle对象和Circle对象,并调用draw函数,会根据对象的实际类型选择正确的函数实现。

多态性使得我们可以以一种统一的方式来处理不同类型的对象,而不需要关心对象的具体类型。这样可以使代码更具灵活性和可维护性,同时提供了一种机制来实现运行时的动态行为。

多态的实现

静态绑定:在编译期决定 函数重载 运算符重载 模板 动态绑定:在程序运行时执行 虚函数

虚函数概念:

在基类中冠以关键字virtual的成员函数 定义: virtual函数类型 函数名称(参数列表) 如果一个函数在基类中被声明为虚函数,则它在所有派生类中都是虚函数。 只有通过基类指针或引用调用虚函数才能引发动态绑定 虚函数不能声明为静态 如果一个类要做为多态基类,要将析构函数定义为虚函数

虚表指针

虚函数的动态绑定是通过虚表来实现的 包含虚函数的类头4个字节存放指向虚表的指针

overload

成员函数被重载的特征: 相同的范围(在同一类中) 函数名字相同 参数不同 virtual关键字可有可无

overwrite

覆盖是指派生类函数覆盖基类函数 特征是: 不同的范围 函数名字相同 参数相同 基类函数必须有virtual关键字

override

重定义(派生类与基类) 不同的范围(分贝位于派生类和基类) 函数名与参数都相同,无virtual关键字 函数名相同,参数不同,virtual可有可无

抽象类

作用: 抽象类作为抽象设计的目的而声明,将有关的数据和行为组织在一个继承层次结构中,保证派生类具有要求的行为。 对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现 注意: 抽象类只能作为基类来使用 不能声明抽象类的对象,可以使用抽象类的指针和引用 构造函数不能是虚函数,析构函数可以是虚函数 可以试用指向抽象类的指针支持运行时多态性 派生类中必须实现基类中的纯虚函数,否则被看做一个抽象类

对于一个没有任何接口的类,如果想要将它定义成抽象类,只能将虚构函数声明为纯虚的 通常情况下在基类中纯虚函数不需要实现,例外是纯析构函数要给出实现

重载

在C++中,函数重载(Function Overloading)是指在同一个作用域内,可以定义多个具有相同名称但参数列表不同的函数。通过函数重载,可以根据参数的类型、顺序和个数来区分不同的函数,并且可以为相同的操作提供不同的实现。

函数重载的特点如下:

函数名称相同:重载的函数必须具有相同的名称。

参数列表不同:重载的函数必须具有不同的参数列表,可以通过参数的类型、顺序和个数的不同来区分。

返回值类型不同不足以实现函数重载:函数的返回值类型不能作为重载函数的区分标准,因为函数调用时通常会忽略返回值。

举例如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
using namespace std;

class interage
{
    int inter;
    public:
        interage(int in)
        {
            inter = in;
        };
        ~interage(){};
        interage& operator++()
        {
            ++inter;
            return *this; 
        }
        interage operator++(int in)
        {
            interage temp(inter);
            inter++;
            return temp;
        }

        void display()
        {
            cout<<inter<<endl;
        }

};
int main()
{
    interage in(10);
    in.display();
    interage in2 = ++(++in);
    in2.display();
    
    interage in3 = in2++;
    in3.display();
    in3.display();
    return 0;
}

通过函数重载,我们可以在C++中实现更加灵活和易于使用的代码。函数重载允许我们使用相同的函数名,但根据参数的类型、顺序和个数来区分不同的函数。这样,我们可以提供不同的函数实现来处理各种情况,而无需为每种情况编写不同的函数名称。

函数重载使得代码更具可读性和可维护性,同时提供了一种方便的方式来进行函数扩展和适应不同的需求。然而,在使用函数重载时,需要注意避免产生歧义或混淆,确保函数之间的区分明确。

总而言之,函数重载是C++中一个强大的特性,可以使代码更加灵活和易于使用,为我们提供了更多的选择和可能性。合理地利用函数重载,可以使我们的代码更加清晰、高效,同时提高开发效率和代码的可维护性。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
《C++中的面向对象编程三大特性:封装、继承与多态》
在 C++编程的广阔世界中,面向对象编程(Object-Oriented Programming,OOP)的三大特性——封装、继承和多态,犹如三把强大的利器,帮助程序员构建出高效、可维护和可扩展的软件系统。本文将深入探讨如何在 C++中实现这三大特性,并通过具体的代码示例展示它们的强大之处。
程序员阿伟
2024/12/09
1620
今天你学C++了吗?——C++中的多态
具体来说,运行时多态允许我们在完成某个行为(函数)时,传入不同的对象就会完成不同的行为,从而达到多种形态。假设我们正在开发一个图形绘制应用程序,该程序需要支持多种图形对象(如圆形、矩形和三角形)的绘制。我们可以设计一个基类Shape,并在其中定义一个虚函数draw()用于绘制图形。不同的图形对象(圆形、矩形和三角形)将作为Shape的派生类,并在这些派生类中重写draw()函数以实现各自的绘制逻辑。同样地,在动物叫声的模拟中,传入猫对象时发出“喵”的叫声,传入狗对象时发出“汪汪”的叫声,这也是通过多态性来实现的。
用户11352420
2025/03/16
1410
今天你学C++了吗?——C++中的多态
解锁C++多态的魔力:灵活与高效的编码艺术(上)
多态性是面向对象编程的重要特性之一,而C++通过虚函数、继承等机制实现了这一强大的功能。多态性使得代码更加灵活和可扩展,允许不同类型的对象以统一的方式进行操作。在本篇文章中,我们将深入探讨C++中多态的实现原理、使用场景及其优劣势,并通过具体代码示例展示如何利用多态来提升代码的可维护性和复用性。
suye
2024/10/18
2320
解锁C++多态的魔力:灵活与高效的编码艺术(上)
C++中高级工程师入门指南-慕K
计模式是在软件开发过程中,经过实践积累而形成的一套解决常见问题的最佳实践方法。设计模式是软件开发中的宝贵工具,它们可以帮助开发人员更快速、更有效地解决常见问题,提高代码质量,减少重复劳动,并促进团队间的合作与共享。
用户11121703
2024/05/25
1670
【C++篇】灵动之韵:C++多态之舞,赋予代码生命的艺术
多态,即多种形态,在面向对象编程中意味着可以通过一个基类指针或引用调用不同派生类的成员函数。多态性使得对象可以被作为其基类类型进行操作,而在运行时实际调用的是派生类的实现。
半截诗
2024/10/11
2320
【C++篇】灵动之韵:C++多态之舞,赋予代码生命的艺术
封装、继承与多态究极详解(面试必问)
继承是类与类之间的一种关系表现,我们知道除了继承,类之间的关系还可以有关联、依赖、实现、聚合、组合,为什么只强调继承?私以为实现是继承的特例,而其他四种关系都属于将类放在不同位置的灵活使用,且C中的结构体本身也具有这些特性,它并不是C++新创造出来的,但继承不一样,继承是新的需要提前约定的规则。
码事漫谈
2024/12/20
1890
聊下继承与多态的区别?
众所周知,C++有三大特性和五大原则,这三大特性分别是:封装、继承和多态。然而继承和多态这两个特性是许多人容易混淆的。
灿视学长
2021/05/28
6K0
基类派生类多态虚函数?
通常在层次关系的根部有一个基类,其他类则直接或间接的从基类继承而来,这些继承得到的类称为派生类。基类负责定义在层次关系中所有类共同拥有的成员,而每个派生类定义各自特有的成员。
洁洁
2023/10/10
2710
【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】
函数声明形式 纯虚函数在声明时有其特定的语法形式,如 virtual 函数类型 函数名(参数列表) = 0;。以之前提到的 Base 类中的 virtual void Func() = 0; 为例,virtual 关键字表明这是一个虚函数,而最后的 = 0 则明确指出它是纯虚函数,意味着该函数在当前类(这里是 Base 类)中不提供具体的函数实现(也就是没有函数体),仅预留函数名和参数列表等信息,等待派生类去完善其具体功能。
Rossy Yan
2024/12/24
1170
【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】
C++基础(七).多态(2)
代码示例 shape.cpp #include <iostream> //cout,endl 相关函数的声明 #define PI 3.1415926 //定义一个PI宏 using namespace std; //设定名称空间 class Shape //定义一个Shape的抽象基类 { public: virtual float getArea()=0; //声明一个纯虚函数 Shape(float x=0); //声明一个带默认参值的构造函数 protected: float h
franket
2021/09/15
4430
C++面向对象编程一些拾遗
虽然说是拾遗,但是这里有一大部分是我以前没有看过的,简书的markdown不支持生成目录,可能需要手动来一个了。
和蔼的zhxing
2018/09/04
7200
C++面向对象编程一些拾遗
C++多态与虚函数
SarPro
2024/02/20
2180
【C++面向对象——类的多态性与虚函数】编写教学游戏:认识动物(头歌实践教学平台习题)【合集】
三个派生类Dog Frog Bird 分别 public继承 Animal,每个派生类会重新定义自己的move()和shout()
Rossy Yan
2024/12/24
2690
【C++面向对象——类的多态性与虚函数】编写教学游戏:认识动物(头歌实践教学平台习题)【合集】
第十四章:C++虚函数、继承和多态详解
C++的虚函数、继承和多态是面向对象编程中非常重要和核心的概念。虚函数允许在派生类中重新定义基类的函数,通过继承和多态可以实现统一的接口和不同对象的不同行为。本文将详细讲解C++中虚函数、继承和多态,并结合代码和实际案例进行演示。
GeekLiHua
2025/01/21
1520
c++类和继承面试点25连问
c++的三大特性,说白了其实就是面向对象的三大特性,是指:封装、继承、多态,简单说明如下:
cpp加油站
2021/06/29
1K0
【C++】自学终极笔记
2. main()函数的返回类型可以是任意的数据类型,而且是唯一一个非void型【 即void main()】可以不用return,因为main()由操作系统直接控制,不能被其他函数调用。
SarPro
2024/02/20
2720
【C++】自学终极笔记
C++虚函数
虚函数是动态多态性的基础,其调用的方式是动态联编(又称晚期联编,简单解释为只有在程序运行时才决定调用基类的还是子类的,系统会根据基类指针所指向的对象来决定要调用的函数);
卡尔曼和玻尔兹曼谁曼
2019/01/25
1.2K0
C++虚函数
多态性 - C++中实现运行时多态的方式
C++中的多态性是指同一个函数可以有多种不同的实现方式,并且在运行时根据实际情况进行选择执行。在C++中实现多态有两种方式:静态多态和动态多态。静态多态是指在编译时确定函数的实现,包括函数重载和模板函数;动态多态是指在运行时根据对象的实际类型来确定函数的实现,包括虚函数和抽象类。
很酷的站长
2023/09/01
4860
多态性 - C++中实现运行时多态的方式
C++基础——C++面向对象之重载与多态基础总结(函数重载、运算符重载、多态的使用)
原文链接:https://winter.blog.csdn.net/article/details/129397401
Winter_world
2023/03/09
1.1K0
C++基础——C++面向对象之重载与多态基础总结(函数重载、运算符重载、多态的使用)
C++ 类、继承、重载《Rice C++ 学习开发》
作者有个自己的想法,如果C语言编写开发中,能把面向对象的思想添加进去,可以让代码更加美观,更加简洁,特别是代码复用。要让代码实现《高内聚、低耦合》,这样写代码才比较有意义。工作一年后,发现读大学的时候,做项目的代码感觉就像一坨shi一样。只要想到什么就写什么,完全没有代码复用的概念。
Rice加饭
2022/05/09
6790
相关推荐
《C++中的面向对象编程三大特性:封装、继承与多态》
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验