C++:类与对象(上):类结构体概念、访问限定符、对象实例化、类对象模型

news2024/11/24 20:10:31

目录

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

1.1 面向过程

1.2 面向对象

二、初步了解类与结构体

2.1 结构体(struct)

2.2 类(class)

三、类

3.1 语法

3.2 定义方式

3.2.1 不分文件编写

3.2.2  分文件编写(常用)

四、类的访问限定符及封装

4.1 访问限定符

4.2 封装

五、类的实例化

六、 类的对象模型

6.1 如何计算类示例的对象大小

6.2 类对象的存储方式猜测

6.3.1 对象中包含类的各个成员(变量+函数)

6.3.2 代码只保存一份,在对象中保存存放代码的地址

6.3.3 只保存成员变量,成员函数存放在公共的代码段


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

面向过程(Procedural Programming)和面向对象(Object-Oriented Programming)是两种不同的编程范式。它们在程序设计的思想、结构和实现方式上有显著的区别。

1.1 面向过程

面向过程是一种基于过程(或函数)的编程方式。在面向过程编程中,程序的执行流程通过依次执行一系列函数或过程来实现。数据和函数是分离的,即数据和操作数据的函数是分开的。程序被分解为多个子任务,每个子任务由一个或多个函数来完成。面向过程的编程风格适合简单、线性的问题,但随着问题的复杂性增加,程序可能变得难以维护和扩展。

特点:

  • 程序由函数组成,函数是核心概念
  • 数据和函数是分离的。
  • 适合简单、线性的问题。
  • 编程的思想更加自顶向下

示例:

#include <stdio.h>

// 函数:计算矩形的面积
float calculateArea(float length, float width) {
    return length * width;
}

// 函数:计算矩形的周长
float calculatePerimeter(float length, float width) {
    return 2 * (length + width);
}

int main() {
    float length = 5;
    float width = 3;
    float area = calculateArea(length, width);
    float perimeter = calculatePerimeter(length, width);

    printf("矩形的面积:%.2f\n", area);
    printf("矩形的周长:%.2f\n", perimeter);

    return 0;
}

1.2 面向对象

面向对象是一种以对象为中心的编程方式。在面向对象编程中,将数据和操作数据的函数(称为方法)封装在一起,形成对象。对象是类的实例,类是对象的抽象。通过类定义了对象的属性(数据)和方法(行为),并且可以通过继承机制派生出子类,实现代码的复用和扩展性。面向对象的编程风格更加灵活和模块化,适合处理复杂问题。

特点:

  • 程序由对象组成,对象是核心概念
  • 数据和操作数据的方法封装在一起。
  • 适合处理复杂、多层次的问题。
  • 编程的思想更加自底向上

示例:

#include <iostream>

class Rectangle {
public:
    // 构造函数
    Rectangle(float length, float width) {
        this->length = length;
        this->width = width;
    }

    // 方法:计算矩形的面积
    float calculateArea() {
        return length * width;
    }

    // 方法:计算矩形的周长
    float calculatePerimeter() {
        return 2 * (length + width);
    }

private:
    float length;
    float width;
};

int main() {
    float length = 5;
    float width = 3;

    // 创建Rectangle对象
    Rectangle rectangle(length, width);

    // 计算面积和周长
    float area = rectangle.calculateArea();
    float perimeter = rectangle.calculatePerimeter();

    std::cout << "矩形的面积:" << area << std::endl;
    std::cout << "矩形的周长:" << perimeter << std::endl;

    return 0;
}

在面向过程示例中,我们使用了函数来执行计算,而在面向对象示例中,我们创建了一个名为Rectangle的类,封装了数据(长度和宽度)和相关的方法(计算面积和周长)。C++的面向对象编程使代码更加模块化和可扩展,适合处理复杂问题。

二、初步了解类与结构体

2.1 结构体(struct)

特点:

  • 结构体是C语言中的一种数据类型,也被许多其他编程语言所支持。
  • 结构体可以包含多个不同类型的成员变量(字段),这些字段在内存中是依次存储的。
  • 结构体没有成员函数(方法),包含数据成员。
  • 默认情况下,结构体的成员是公共的(public),所有的代码都可以直接访问结构体的成员。
  • 结构体不能继承其他结构体或类型。
  • 结构体的定义类似于类似于变量定义,使用关键字struct

示例:

#include <stdio.h>

// 定义矩形结构体
struct Rectangle {
    float length; // 矩形的长度
    float width;  // 矩形的宽度
};

int main() {
    // 创建Rectangle结构体变量
    struct Rectangle rect;

    // 初始化矩形的长度和宽度
    rect.length = 5.0;
    rect.width = 3.0;

    // 计算矩形的面积和周长
    float area = rect.length * rect.width;
    float perimeter = 2 * (rect.length + rect.width);

    return 0;
}

2.2 类(class)

特点:

  1. 类是面向对象编程(如C++)中的概念,用于创建自定义的数据类型
  2. 类可以包含数据成员(属性)和成员函数(方法),将数据和操作数据的方法封装在一起。
  3. 类可以实现访问控制,通过关键字publicprivateprotected来定义成员的可访问性
  4. 类支持继承机制,可以派生出子类,实现代码的复用和扩展性。
  5. 类是对象的抽象,对象是类的实例化。在使用类创建对象时,对象会占用内存并包含类定义中的成员变量和成员函数。

示例:

#include <iostream>

// 定义矩形类
class Rectangle {
public:
    float length; // 矩形的长度
    float width;  // 矩形的宽度

    // 计算矩形的面积
    float calculateArea() {
        return length * width;
    }

    // 计算矩形的周长
    float calculatePerimeter() {
        return 2 * (length + width);
    }
};

int main() {
    // 创建Rectangle对象
    Rectangle rect;

    // 初始化矩形的长度和宽度
    rect.length = 5.0;
    rect.width = 3.0;

    // 计算矩形的面积和周长
    float area = rect.calculateArea();
    float perimeter = rect.calculatePerimeter();

    return 0;
}

提醒:

在C++当中,structclass具有相同功能,struct可以当作类的关键字使用,在结构体内定义数据与函数进行封装,同时也可以使用访问限定符但是在C++中更加倾向于使用class定义类。同时,C语言中的struct关键字定义的结构体内部的数据是默认公有的,通过结构体定义的变量可以直接访问,相当与C++类中的public权限,C++类中的数据和函数是默认私有的,类外无法进行访问,根据实际情况使用三种访问限定符。

注意:在继承和模板参数列表位置,struct和class也有区别,后序介绍。

三、类

3.1 语法

class className
{
    // 类体:由成员函数和成员变量组成
};  // 一定要注意后面的分号

class为定义类的关键字className类的名字{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为成员属性或成员变量; 类中的函数称为成员方法或者成员函数

3.2 定义方式

3.2.1 不分文件编写

#ifndef RECTANGLE_H
#define RECTANGLE_H

// 定义矩形类
class Rectangle {
public:
    // 构造函数:初始化矩形的长度和宽度
    Rectangle(float length, float width);

    // 成员函数:计算矩形的面积
    float calculateArea();

    // 成员函数:计算矩形的周长
    float calculatePerimeter();

private:
    float length; // 矩形的长度
    float width;  // 矩形的宽度
};

#endif



此代码仅作功能演示使用,读者遇到陌生的概念语法等会在后续文章进行讲解。
需注意成员函数如果在类中定义,编译器可能会将其当成内 联函数处理。

3.2.2  分文件编写(常用)

Rectangle.h(头文件)

#ifndef RECTANGLE_H
#define RECTANGLE_H

// 定义矩形类
class Rectangle {
public:
    // 构造函数:初始化矩形的长度和宽度
    Rectangle(float length, float width);

    // 成员函数:计算矩形的面积
    float calculateArea();

    // 成员函数:计算矩形的周长
    float calculatePerimeter();

private:
    float length; // 矩形的长度
    float width;  // 矩形的宽度
};

#endif

Rectangle.cpp(实现文件)

#include "Rectangle.h"

// 构造函数的实现
Rectangle::Rectangle(float length, float width) {
    this->length = length;
    this->width = width;
}

// 成员函数:计算矩形的面积
float Rectangle::calculateArea() {
    return length * width;
}

// 成员函数:计算矩形的周长
float Rectangle::calculatePerimeter() {
    return 2 * (length + width);
}

注意:成员函数名前需要加类名::,表明该函数定义属于此类。

四、类的访问限定符及封装

4.1 访问限定符

C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选 择性的将其接口提供给外部的用户使用。

在C++中,类的访问限定符用于控制类的成员(成员变量和成员函数)对外部的可见性和访问权限。类的访问限定符有三种:publicprivateprotected。这些访问限定符决定了类的成员在哪些地方可以被访问。

1. public

  • public是默认的访问限定符,如果不指定访问限定符,默认为public。
  • public成员可以在类的外部访问,也可以在类的内部访问。

2. private:

  • private成员只能在类的内部访问,不能在类的外部直接访问。
  • private成员用于隐藏实现细节,将数据隐藏在类的内部,防止外部代码直接访问和修改。

3. protected

  • protected成员与private成员类似,也只能在类的内部访问。
  • 但protected成员对于派生类(子类)来说是可见的,允许派生类访问基类的protected成员

说明:

  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有访问限定符,作用域就到 } 即类结束。
  • 访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。

4.2 封装

封装是面向对象编程的一个重要特性,它允许类将数据和对数据的操作封装在一起,形成一个独立的实体。封装通过将数据成员设置为私有的(private),从而保护了数据的安全性,并通过公共的(public)成员函数来实现对数据的访问和修改。这样外部代码只能通过公共接口来访问和操作数据,无法直接访问私有成员,从而隐藏了实现细节,使得类的内部结构和数据对外部代码是不可见的。

封装优点:

  • 数据隐藏和安全性:类的私有成员对外部代码不可见,避免了直接访问和修改数据,保护了数据的安全性。
  • 简化接口:公共成员函数提供了类与外部交互的接口,隐藏了内部实现细节,使得使用类的代码更简洁、易读。
  • 代码重用:类的接口可以被其他代码重用,提高了代码的可维护性和重用性。

五、类的实例化

在面向对象编程中,类的实例化是指通过类创建一个对象的过程。类定义了一种自定义的数据类型,而类的实例化就是使用该数据类型创建一个具体的实体,也称为对象。通过实例化,我们可以使用类的成员函数和成员变量来操作对象的数据和行为。

做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类的定义也只是一个蓝图,实例化出的对象才能实际存储数据,占用实际物理空间

示例:

class Person{
    //类定义
}

int main(){
    //实例化出对象p
    Person p;
}

六、 类的对象模型

6.1 如何计算类示例的对象大小

class Person{
private:
    int _count;

public:
    void print(){
        cout << "Hello World" << endl;
    }
};

类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算 一个类的大小?值得我们深思!我们应该思考类是被如何存储的!

6.2 类对象的存储方式猜测

6.3.1 对象中包含类的各个成员(变量+函数)

思考:每个对象内部的成员变量时不相同的,但是函数如同我们平时使用的函数相同,只需要有一份代码即可,如果按照这种方式进行存储,每个对象中都存储一份函数代码,会造成空间浪费,稍加思考也能想到此种方法时行不通的!!

6.3.2 代码只保存一份,在对象中保存存放代码的地址

 此种方法相对第一种方法自然是节省了不少空间,那么让我们在具体环境中简单验证一下!

 由此可得,实例化对象中只存储了int变量,并没有所谓的指针。看看第三种!

6.3.3 只保存成员变量,成员函数存放在公共的代码段

类对象模型将成员变量保存在对象的内存中,而成员函数通常存放在公共的代码段中(也称为代码区、代码段或文本段)。这种设计有助于节省内存空间,因为成员函数在不同的对象实例之间是共享的,而不需要每个对象都保存一份。

当你调用一个类的成员函数时,实际上是通过对象的指针来访问公共的代码段中的函数代码。具体的调用过程如下:

  1. 创建类的对象:通过类的构造函数创建一个新的对象实例,其中包括成员变量的内存。

  2. 使用对象的指针:要调用对象的成员函数,你需要使用指向该对象的指针。

  3. 访问成员函数:通过指针访问对象的成员函数。使用箭头运算符(->)来访问通过指针指向的对象的成员函数。

#include <iostream>

class MyClass {
public:
    int myVar;

    void nonVirtualFunction() {
        std::cout << "This is a non-virtual function" << std::endl;
    }

    virtual void virtualFunction() {
        std::cout << "This is a virtual function" << std::endl;
    }
};

int main() {
    MyClass obj1;
    MyClass obj2;

    obj1.nonVirtualFunction(); // 调用非虚函数
    obj1.virtualFunction(); // 调用虚函数

    MyClass* ptr = &obj2;
    ptr->nonVirtualFunction(); // 使用指针调用非虚函数
    ptr->virtualFunction(); // 使用指针调用虚函数

    return 0;
}

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

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

相关文章

SpringBoot案例-部门管理-查询

查看页面原型&#xff0c;明确需求需求 页面原型 需求分析 阅读接口文档 接口文档链接如下&#xff1a; https://onedrive.live.com/?cidC62793E731F0C1BE&idC62793E731F0C1BE%2148 思路分析 用户发送请求&#xff0c;交由对应的Controller类进行处理&#xff0c;Con…

初识Java集合框架

前言 在大多数情况下&#xff0c;你常常会看到《C数据结构》类似的书籍&#xff0c;很多人可能会认为数据结构是一门依赖语言的学科&#xff0c;有了语言才可能有数据结构&#xff0c;其实这里需要纠正的是&#xff0c; 数据结构(Data Structure)是计算机存储、组织数据的方式…

二、web核心防御机制(上)

文章目录 一、Web应用程序与风险1.1 Web应用程序的发展历程1.2 Web应用程序安全 二、核心防御机制2.1 处理用户访问2.2 处理用户输入2.2.1输入的多样性2.2.2 输入处理方法2.2.3 边界确认2.2.4 多步确认与规范化 一、Web应用程序与风险 1.1 Web应用程序的发展历程 在因特网发展…

Xception 算法详解

📮 本次重点(模型轻量化): ● Inception设计理念 ● 点卷积 ● 深度可分离卷积 ● Bottleneck结构 注:Xception算法整体结构是其次,主要是了解以上四个结构。 今天详解Xception算法,由于Xception模型在极大的减少了网络参数量和计算复杂度的同时,可以保持卓越的性能表…

优思学院|精益生产3大特征:拉动式生产、消除浪费、自働化

在现代制造业中&#xff0c;精益生产作为一种高效的生产方式&#xff0c;受到了广泛的关注和应用。它的核心理念是通过最大程度地减少浪费和提高效率来实现生产过程的优化。经典的精益体系从中提炼出了精益生产的三大特征&#xff0c;分别是拉动式生产、消除浪费以及自働化。让…

JSON.stringify循环引用问题

前端使用到对象的深度复制通常会简单的使用JSON.parse(JSON.stringify(obj))实现 &#xff08;浅表复制会用Array.from、Object.assign、Object.create静态方法实现&#xff09;&#xff0c;但在对象存在循环引用的情况下&#xff08;比如&#xff1a;树结构中子对象存在parent…

使用JavaScript实现页面滑动切换效果

使用JavaScript实现页面滑动切换效果 在现代Web页面设计中&#xff0c;页面滑动切换效果已经成为了一种常见的设计要求&#xff0c;能够提升用户体验&#xff0c;增加页面的交互性。本文将通过JavaScript来实现这一效果。 首先&#xff0c;我们需要在HTML中添加一些基础结构和…

Linux 环境 nginx安装

这里写自定义目录标题 前言安装nginx依赖下载并解压nginx安装包和ngx_http_proxy_connect_module模块解压nginx安装包 和 ngx_http_proxy_connect_module模块编译ngx_http_proxy_connect_module模块和安装nginx感谢 前言 确定环境是有网的环境&#xff0c;且yum源可用&#xf…

【广州华锐视点】VR燃气轮机故障判断模拟演练系统

VR燃气轮机故障判断模拟演练系统由广州华锐视点开发&#xff0c;是一款基于虚拟现实技术的教育工具&#xff0c;旨在为学生提供一个安全、高效、互动的学习环境&#xff0c;帮助他们更好地掌握燃气轮机的故障诊断技能。 这款VR实训软件能够模拟真实的燃气轮机故障诊断场景&…

一种水文水利行业满管非满管双声道流量计安装调试

供电电源 用户应该特别注意&#xff1a;若是交流&#xff08;AC220V&#xff09;供电的主机插入直流电源&#xff0c;或者直流&#xff08;DC24V&#xff09;供电的主机接入AC220V电源&#xff0c;就会把流量计烧毁。 普通主机&#xff08;包括固定式主机、盘装式主机&#x…

Android之消除APP图标的白色边框

有问题的效果&#xff1a; 解决方案&#xff1a; 第一步&#xff1a;app右键—>new—>Image Asset 第二步&#xff1a;上传Logo图标&#xff0c;选择每种分辨率&#xff0c;预览看效果&#xff0c;选择Resize&#xff0c;可以微调 第三步&#xff1a;点击 Next&#xff…

RFID工业识别技术:供应链智能化的科技颠覆

RFID工业识别技术&#xff0c;作为物联网的先锋&#xff0c;正在供应链管理领域展现着前所未有的科技颠覆。从物料追踪到库存管理&#xff0c;再到物流配送&#xff0c;RFID技术以其高效的数据采集和智能的自动化处理&#xff0c;彻底改变着传统供应链的运营方式。 RFID在物料追…

C++之std::pair与vector<pair>用法(一百七十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

传统图像算法 - 运动目标检测之KNN运动背景分割算法

以下代码用OpenCV实现了视频中背景消除和提取的建模&#xff0c;涉及到KNN&#xff08;K近邻算法&#xff09;&#xff0c;整体效果比较好&#xff0c;可以用来进行运动状态分析。 原理如下&#xff1a; 背景建模&#xff1a;在背景分割的开始阶段&#xff0c;建立背景模型。 …

【C语言】扫雷 小游戏

文章目录 一、游戏规则二、 代码逻辑三、游戏实现1. 游戏菜单设计2.设计雷区并随机布置雷(1) 设置雷区(2) 布置雷 3.排查雷 四、源码 一、游戏规则 1. 在9*9的小格子中&#xff0c;任意选取一个坐标&#xff08;格子&#xff09;&#xff0c;选择后发现&#xff0c;如果没点中雷…

UE5、CesiumForUnreal接入WMTS格式地图瓦片,如ArcGIS、Mapbox、天地图

文章目录 1.实现目标2.实现过程2.1 WMTS与TMS2.2 cesium-native改造2.3 CesiumForUnreal插件改造2.4 WMTS瓦片加载测试2.5 EPSG:3857与43263.参考资料1.实现目标 通过改造cesium-native和CesiumForUnreal插件,参考tms的栅格瓦片地图加载逻辑,实现在UE5中通过CesiumForUnreal…

问道管理:信创概念走势活跃,恒银科技斩获四连板

信创概念9日盘中走势活泼&#xff0c;截至发稿&#xff0c;新晨科技、竞业达、恒银科技等涨停&#xff0c;宇信科技涨近10%&#xff0c;中孚信息涨近9%&#xff0c;华是科技、神州数码涨超7%。 新晨科技今天“20cm”涨停&#xff0c;公司昨日晚间公告&#xff0c;近来收到投标代…

HarmonyOS应用开发者基础认证考试题库

此博文为HarmonyOS应用开发者基础认证考试的最后的大考&#xff0c;要求100分取得90分方可获取证书、现将考试的题库进行分享&#xff0c;希望能帮到大家。但是需要注意的是&#xff0c;题库会不定时的进行题目删减&#xff0c;但是大概的内容是不会进行改变的。真心希望这篇博…

ModaHub魔搭社区——GPTCache是如何工作的?

在线服务通常表现出数据局部性,用户经常访问流行或趋势内容。缓存系统通过存储通常访问的数据来利用这种行为,这反过来减少了数据检索时间,提高了响应时间,并减轻了后端服务器的负担。传统缓存系统通常利用新查询和缓存查询之间的精确匹配来确定请求的内容在获取数据之前是…