C++从入门到精通——初步认识面向对象及类的引入

news2024/11/19 18:31:59

初步认识面向对象及类的引入

  • 前言
  • 一、面向过程和面向对象初步认识
    • C语言
    • C++
  • 二、类的引入
    • C++的类名代表什么
      • 示例
    • C++与C语言的struct的比较
      • 成员函数
      • 访问权限
      • 继承
      • 默认构造函数
      • 默认成员初始化
      • 结构体大小
    • 总结


前言

面向过程注重任务的流程和控制,适合简单任务和流程固定的场景;而面向对象则将数据和功能封装成对象,通过对象间的交互实现复杂功能,更适用于大型、复杂的软件系统开发。

类的引入是面向对象编程中的一个核心概念。通过类,我们可以创建具有相同属性和行为的对象,从而实现代码的重用和模块化。类定义了对象的结构和行为,包括对象的属性(数据成员)和方法(成员函数)。通过实例化类,我们可以创建对象,并赋予它们特定的属性值。这样,每个对象都具有独特的身份,但仍然共享类的定义和行为。类的引入使得代码更加组织化、可维护性和可扩展性,提高了软件开发效率和质量。


一、面向过程和面向对象初步认识

当我们开始接触编程时,首先遇到的两个核心概念便是面向过程(Procedural Programming)和面向对象(Object-Oriented Programming,简称OOP)。这两种编程范式各有其特点,并且在不同的应用场景中发挥着各自的优势。

面向过程编程,顾名思义,是以一系列按照特定顺序执行的过程或函数为核心来构建程序的。在这种编程范式中,程序员会定义一系列函数,每个函数负责完成特定的任务,然后通过一个主程序来调用这些函数,以实现特定的功能。面向过程编程的优点在于其直观性和简单性,特别适用于小规模、逻辑清晰的程序。然而,随着程序规模的扩大和复杂度的提升,面向过程编程的缺点也逐渐暴露出来,如代码重复、难以维护、可扩展性差等。

与面向过程编程不同,面向对象编程将现实世界中的事物抽象为对象,每个对象都拥有属性和方法。对象之间可以通过消息传递进行交互,从而实现复杂的功能。面向对象编程的核心概念包括类(Class)、对象(Object)、继承(Inheritance)、封装(Encapsulation)和多态(Polymorphism)。通过这些概念,面向对象编程能够更好地模拟现实世界,提高代码的可重用性、可维护性和可扩展性。

在实际应用中,面向过程和面向对象编程往往不是孤立的,而是相互补充的。对于某些特定的任务或模块,使用面向过程编程可能更加合适;而对于整个系统或大型项目,采用面向对象编程则能够更好地组织和管理代码。因此,作为程序员,我们需要根据具体的需求和场景来选择合适的编程范式,以达到最佳的开发效果。

C语言

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
在这里插入图片描述

在这里插入图片描述

C++

C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

在这里插入图片描述
在这里插入图片描述

二、类的引入

类的引入在编程中是一个核心概念,它允许我们创建具有相似属性和行为的对象集合。通过定义类,我们可以封装数据(属性)和功能(方法),从而创建出具有特定特性和行为的对象。这种封装不仅提高了代码的可读性和可维护性,还增强了代码的重用性。

C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:之前在我之前用C语言写的数据结构的文章中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现,会发现struct中也可以定义函数。

总结:c++兼容C语言中的struct用法,但是c++将struct升级成了类

C++的类名代表什么

在C++中,类名代表了一种自定义的数据类型。类是一种用户定义的数据类型,可以封装数据和成员函数,以实现特定的功能。

类定义了一组数据成员和成员函数,用于描述对象的状态和行为。数据成员表示对象的属性和状态,而成员函数用于定义对象的行为和操作。

通过创建类的对象,我们可以实例化该类并使用类的成员函数来操作对象的数据。类提供了一种封装数据和功能的机制,使得代码可以更加模块化和可维护。

类名在C++中是用来标识该类的唯一标识符。通常按照一定的命名规范(如驼峰命名法)命名类名,以便于代码的可读性和可理解性。类名是用来声明类变量、创建对象和调用类的成员函数的重要标识符。

示例

在C语言中我们定义一个链表是按照下面的方式来定义的

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

在C++中定义一个链表却是按照下面这个方式来定义

 struct SListNode
{
	SLTDataType data;
	SListNode* next;
};

C++中的struct具有与类相同的能力,可以封装数据和成员函数。

C++与C语言的struct的比较

C++与C语言中的struct在定义和使用上有一些区别。

成员函数

C++的struct可以包含成员函数,而C语言的struct只能包含成员变量。

以下是一个使用C++中的struct定义一个包含成员函数的示例:

#include <iostream>

struct Person {
	//成员变量
    std::string name;
    int age;
	//成员函数
    void display() {
        std::cout << "Name: " << name << ", Age: " << age <<std::endl;
    }
};

int main() {
    Person p1;
    p1.name = "John";
    p1.age = 25;
    p1.display();

    return 0;
}

上述示例中,我们定义了一个名为Personstruct,它包含了两个成员变量nameage,还有一个成员函数display()。在main函数中,我们创建了一个Person对象p1,并为其成员变量赋值,然后通过调用p1.display()函数来显示该对象的信息。

而在C语言中,如下

struct Person {
 
    int age;
};
void display() {
       ……
    };

上述示例中,我们可见C语言的结构体只能定义成员变量

访问权限

C++中的struct成员默认为public,而C语言中的struct成员默认为public。这是因为C++要兼容C,所以都是public,关于public可以看我的下一篇文章。

在C++中,structclass的主要区别在于默认访问权限。下面是一个示例,展示了C++中的struct成员默认为public,而C语言中的struct成员默认为public的区别:

#include <iostream>

// C++中的struct,默认成员为public
struct Person {
    std::string name;
    int age;

    void display() {
        std::cout << "Name: " << name << ", Age: " << age << std::endl;
    }
};

int main() {
    Person p1;
    p1.name = "John";
    p1.age = 25;

    p1.display();

    return 0;
}

在上述示例中,我们定义了一个名为Personstruct,它包含了一个string类型的name和一个int类型的age。还有一个名为display的成员函数,用于显示该结构体的信息。

我们可以直接访问struct的成员变量和成员函数,无需使用任何访问修饰符。在main函数中,我们创建了一个Person类型的结构体变量p1,并为其成员变量赋值。然后,在display函数中,我们通过p1对象直接调用成员函数来显示该结构体的信息。

需要注意的是,C语言中的struct不支持成员函数,默认情况下,所有成员都是公开的,可以直接访问。而C++中的struct可以使用成员函数,而且默认情况下成员是公开的。这是C语言和C++中struct的一个主要区别。

继承

C++的struct可以通过继承来拓展,而C语言的struct不能进行继承。关于继承可以看我的后续文章。

在C++中,可以通过继承来拓展struct,如下所示:

struct Animal {
    int age;
};

struct Cat : public Animal {
    std::string name;
};

int main() {
    Cat cat;
    cat.age = 3;
    cat.name = "Tom";

    return 0;
}

在上面的例子中,Cat结构体从Animal结构体继承,继承后的Cat结构体包含了Animal的成员变量age,并新增了一个成员变量name

而在C语言中,struct无法进行继承。C语言的结构体只能包含成员变量,不能继承其他结构体的成员变量或方法。下面是一个C语言中使用结构体的例子:

typedef struct {
    int age;
} Animal;

typedef struct {
    Animal animal;
    char name[20];
} Cat;

int main() {
    Cat cat;
    cat.animal.age = 3;
    strcpy(cat.name, "Tom");

    return 0;
}

在上面的例子中,Cat结构体包含了Animal结构体的成员变量age,并新增了一个成员变量name。但是这种方式并不是继承,而是嵌套了一个Animal结构体,通过嵌套来实现在Cat中包含Animal的成员变量。

默认构造函数

C++的struct可以有默认构造函数,而C语言的struct没有默认构造函数。

下面是一个具有默认构造函数的C++ struct的例子:

#include <iostream>

struct Person {
    std::string name;
    int age;
    
    // 默认构造函数
    Person() {
        name = "Unknown";
        age = 0;
    }
};

int main() {
    Person person; // 调用默认构造函数
    
    std::cout << "Name: " << person.name << std::endl;
    std::cout << "Age: " << person.age << std::endl;

    return 0;
}

在上述例子中,定义了一个Person结构体,并为其提供了默认构造函数。在默认构造函数中,将name初始化为"Unknown",将age初始化为0。在主函数中,创建了一个Person对象person,由于没有提供任何参数,因此使用了默认构造函数进行初始化。输出结果如下:

Name: Unknown
Age: 0

而在C语言中,struct没有默认构造函数的概念。在C语言中,需要手动为struct的成员变量赋初始值。下面是一个使用C语言的struct的例子:

#include <stdio.h>

struct Person {
    char name[20];
    int age;
};

int main() {
    struct Person person = {"Unknown", 0}; // 手动赋初始值
    
    printf("Name: %s\n", person.name);
    printf("Age: %d\n", person.age);

    return 0;
}

在上述例子中,定义了一个Person结构体,并在主函数中手动为其成员变量赋初始值。通过使用大括号括起来的值列表来初始化结构体对象。输出结果与前面的例子相同:

Name: Unknown
Age: 0

默认成员初始化

C++的struct可以在声明时为成员变量提供默认值,而C语言的struct不支持默认成员初始化。

下面是一个C++ struct中支持默认成员初始化的例子:

#include <iostream>

struct Rectangle {
    int width = 0;  // 默认初始化为0
    int height = 0; // 默认初始化为0
};

int main() {
    Rectangle rectangle; // 使用默认初始化值
    
    std::cout << "Width: " << rectangle.width << std::endl;
    std::cout << "Height: " << rectangle.height << std::endl;

    return 0;
}

在上述例子中,定义了一个Rectangle结构体,并在成员变量的声明时为其提供了默认值。在主函数中,创建了一个Rectangle对象rectangle,由于没有提供任何初始化值,因此会使用成员变量的默认值进行初始化。输出结果如下:

Width: 0
Height: 0

而在C语言中,不支持这种在声明时为成员变量提供默认值的特性。在C语言中,需要在初始化结构体对象时手动为其成员变量赋值。下面是一个使用C语言的struct的例子:

#include <stdio.h>

struct Rectangle {
    int width;
    int height;
};

int main() {
    struct Rectangle rectangle = {0, 0}; // 手动赋初始值
    
    printf("Width: %d\n", rectangle.width);
    printf("Height: %d\n", rectangle.height);

    return 0;
}

在上述例子中,定义了一个Rectangle结构体,并在主函数中手动为其成员变量赋初值。通过使用大括号括起来的值列表来初始化结构体对象。输出结果与前面的例子相同:

Width: 0
Height: 0

结构体大小

C语言中的struct的大小仅受成员变量的大小和对齐方式影响,而C++中的struct除了受成员变量的大小和对齐方式影响,还有可能受到虚函数表的影响。关于虚函数可以看我后续文章。

下面是一个展示C语言和C++中struct大小差异的例子:

在C语言中,struct的大小仅受成员变量的大小和对齐方式的影响,不会受到其他因素的影响。考虑以下示例:

#include <stdio.h>

struct Rectangle {
    int width;
    int height;
};

int main() {
    struct Rectangle rectangle;

    printf("Size of Rectangle: %zu bytes\n", sizeof(rectangle));

    return 0;
}

在上述C语言示例中,定义了一个Rectangle结构体,包含两个int类型的成员变量widthheight。在主函数中,使用sizeof运算符来获取结构体Rectangle的大小并打印输出。

输出结果为:

Size of Rectangle: 8 bytes

在这个例子中,widthheight各占4个字节,所以Rectangle结构体的大小为8字节。

而在C++中,struct除了受成员变量的大小和对齐方式的影响,还有可能受到虚函数表的影响。考虑以下示例:

#include <iostream>

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

struct Rectangle : public Shape {
    int width;
    int height;
};

int main() {
    Rectangle rectangle;

    std::cout << "Size of Rectangle: " << sizeof(rectangle) << " bytes" << std::endl;

    return 0;
}

在上述C++示例中,定义了一个Shape结构体,其中包含一个虚函数draw()。然后定义了一个Rectangle结构体,通过公共继承从Shape继承,并添加了两个int类型的成员变量widthheight

在主函数中,创建了一个Rectangle对象并使用sizeof运算符获取其大小并打印输出。

输出结果为:

Size of Rectangle: 16 bytes

在这个例子中,除了widthheight各占4个字节,还会有额外的字节用于存储虚函数表指针,以便支持多态性。因此,Rectangle结构体的大小为16字节。

这个例子展示了C++中的struct可能受到虚函数表的影响,使得其大小与仅受成员变量大小和对齐方式影响的C语言struct不同。

总结

需要注意的是,尽管C++的struct比C语言的struct功能更强大,但C++中的class更常用于定义对象。C++中的classstruct的唯一区别在于默认访问权限,class中成员默认为private,而struct中成员默认为public


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1573043.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

R155/R156:汽车网络安全新法规快速指南

R155/R156:汽车网络安全新法规快速指南 随着国际机构进入网络安全领域,制定法规、标准和指南,公众在其使用的车辆中享受更好的网络安全保护指日可待。随着时间的推移,车辆网络安全将不断发展以应对不断变化的网络威胁。 欧洲经济委员会 (ECE) 的 R155 和 R156 法规旨在应…

Day30 线程安全之窗口售票问题(含代码)

Day30 线程安全之窗口售票问题&#xff08;含代码&#xff09; 一、需求&#xff1a; 铁道部发布了一个售票任务&#xff0c;要求销售1000张票&#xff0c;要求有3个窗口来进行销售&#xff0c; 请编写多线程程序来模拟这个效果&#xff08; 注意&#xff1a;使用线程类的方式…

数据库 06-04 恢复

01 一.事务故障 二.系统 三.磁盘 02. 重点是稳定存储器 组成

【IEEE STD 1801】——Introduction

Introduction 本标准的目的是提供便携、低功耗的设计规范&#xff0c;这些规范可以在整个电子系统设计、分析、验证和实现流程中与各种商业产品一起使用。 当电子设计自动化(EDA)行业在20世纪80年代开始创建用于指定、仿真和实现数字电子电路的功能规范的标准时&#xff0c;主…

当下鸿蒙开发热潮,大前端开发有没有必要搞!!!

鸿蒙到底好不好&#xff1f;要不要搞&#xff1f; Android开发反正目前工作感觉也不好找&#xff0c;即便是上海这样的大城市也难搞&#xff0c;人员挺饱和的。而且年前裁员的公司那么多&#xff0c;再看自己&#xff0c;年龄不是优势&#xff1b;技术不是优势&#xff0c;想想…

DHCP-PXE

Dynamic Host Configuration Protocol 动态主机配置协议 1.Selinux 调试为Permission 防火墙配置 搭建DHCP的主机必须有一个静态地址&#xff0c;提前配置好 安装DHCP软件 服务名为dhcpd DHCP地址分配四次会话&#xff0c; DISCOVERY发现 OFFER 提供 REQUEST 回应 A…

PHP实现nginxPhp错误日志提取统计工具(路径+错误行+报错信息+次数排序)

粘贴PHP错误日志内容(NGINX 下PHP网站错误日志)。 作用:提取PHP Warning/Notice:路径错误行报错信息按出现次数排序。 以上已满足本人自己LNMP环境的调试需求&#xff0c;其他环境自己评估是否可用。 <?php //整理与分享&#xff1a;yujianyue<15058593138qq.com> $…

国家开放大学电大《钢结构》形考任务答案

电大搜题 多的用不完的题库&#xff0c;支持文字、图片搜题&#xff0c;包含国家开放大学、广东开放大学、超星等等多个平台题库&#xff0c;考试作业必备神器。 公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#x…

腾讯云-域名注册购买实名流程

1&#xff0c;注册并完成实名腾讯云账号 账号实名认证和后续要完成的域名实名认证应为同一主体单位。否则域名实名会不通过 参考链接 腾讯云账号实名 – 易极赞自助建站 2&#xff0c;进入腾讯云域名注册购买地址 推荐购买com&#xff0c;cn&#xff0c;net主流域名&#xf…

LabVIEW深度学习

目录 一、配置环境1.1、显卡选择1.2、下载显卡驱动1.3、下载并安装Anaconda1.4、配置Anaconda软件包下载服务器1.5、配置虚拟环境tf_gpu1.6、安装vscode1.7、安装tensorflow1.8、下载安装Git1.9、安装TensorFlow Object Detection API框架1.10、安装依赖的python软件包1.11、配…

Centos7下docker安装jenkins【使用docker-compose图文教程】

个人记录 前置条件&#xff1a;安装Docker与Docker-compose Centos7安装Docker与Docker-compose【图文教程】 查看jenkins最新的版本 https://www.jenkins.io/download/ 配置docker-compose.yml vim docker-compose.yml按i进行编辑模式&#xff0c;粘贴如下内容。把image里…

After Effects 2024:创意无界,想象成真mac/win版

在数字艺术飞速发展的今天&#xff0c;After Effects 2024已经站在了视觉特效和动态图形设计的最前沿。这款软件不仅继承了之前版本的强大功能&#xff0c;更在细节和效率上进行了全方位的优化和升级。 After Effects 2024软件获取 After Effects 2024为用户提供了更加丰富的特…

A - Penalty Kick

A - Penalty Kick 我又又又回来啦 题目&#xff1a; Problem Statement Takahashi will have N N N penalty kicks in a soccer match. For the i i i-the enalty kick, he will fail if i i i is a multiple of 3 3 3, and succeed otherwise . . . Print the resul…

拦截器抛出异常无法被全局异常处理器捕获问题

文章目录 基本说明问题描述问题原因解决方法前端执行的所有请求都通过Controller&#xff0c;而不是直接访问html定义一个/error路径的方法 总结 基本说明 我的前后端项目是放在一起的&#xff0c;前后端都是由springMVC进行控制&#xff0c;但是现在我在拦截器的preHandle方法…

c# wpf LiveCharts 简单试验2

1.概要 1.1 说明 1.2 要点 1.2.1 添加命名控件 xmlns:lvc"clr-namespace:LiveCharts.Wpf;assemblyLiveCharts.Wpf" 1.2.2 图片控件 <lvc:CartesianChart Name"chart" LegendLocation"Right"/> 1.3 代码文件引用 using LiveCharts…

循环神经网络:揭秘长期记忆的魔法之源

在人工智能和机器学习领域&#xff0c;循环神经网络&#xff08;Recurrent Neural Networks&#xff0c;简称RNN&#xff09;以其独特的架构和机制&#xff0c;在处理序列数据方面展现出了强大的能力。特别值得一提的是&#xff0c;RNN能够学习到长期的记忆&#xff0c;这使得它…

综测仪MT8862A控制方法

实现自动化控制&#xff0c;本次为大家讲解综测仪MT8862A的控制逻辑。 新建底层控制逻辑 在文件basis_contorl.py中写入仪器控制底层代码&#xff0c;代码如下&#xff1a; import tkinter.messagebox import pyvisaclass InstrumentControl(object):inst Nonedef __init__(…

利用Flutter混淆工具提高应用的反编译难度

在移动应用开发中&#xff0c;保护应用代码安全至关重要。Flutter 提供了简单易用的混淆工具&#xff0c;帮助开发者在构建 release 版本应用时有效保护代码。本文将介绍如何在 Flutter 应用中使用混淆&#xff0c;并提供了相关的操作步骤和注意事项。 &#x1f4dd; 摘要 本…

C# 委托的基础应用

一、Action 和 Func 的使用。 二、自定义委托&#xff1a; 完整的使用代码示例&#xff1a; 三、委托的一般使用 模板方法&#xff1a; 回调方法&#xff0c;在模板方法的基础上进行添加。

使用向量检索和rerank 在RAG数据集上实验评估hit_rate和mrr

文章目录 背景简介代码实现自定义检索器向量检索实验向量检索和rerank 实验 代码开源 背景 在前面部分 大模型生成RAG评估数据集并计算hit_rate 和 mrr 介绍了使用大模型生成RAG评估数据集与评估&#xff1b; 在 上文 使用到了BM25 关键词检索器。接下来&#xff0c;想利用向…