C++学习:类和对象(一)

一、面向过程与面向对象编程

1. 什么是面向过程编程?

面向过程编程(Procedural Programming)是一种以过程(或函数)为中心的编程范式。程序被视为一系列按顺序执行的步骤,主要通过函数对数据进行操作

特点:

  • 执行顺序明确:程序按照代码书写的顺序执行
  • 侧重算法:重视具体的操作步骤和实现流程
  • 代码重用性低:相似的功能需要重复编写代码

代码示例:计算数组元素的平均值

#include <iostream>
using namespace std;

int main() {
    const int SIZE = 5;
    int numbers[SIZE] = {5, 10, 15, 20, 25};
    int sum = 0;

    for (int i = 0; i < SIZE; ++i) {
        sum += numbers[i];
    }

    double average = static_cast<double>(sum) / SIZE;
    cout << "平均值是:" << average << endl;

    return 0;
}

2. 什么是面向对象编程?

面向对象编程(Object-Oriented Programming,OOP)是一种以对象为中心的编程范式。它将数据和操作数据的函数封装在一起,称为对象。程序被设计为一组相互交互的对象

特点:

  • 封装(Encapsulation):将数据和相关操作封装在对象内部,保护数据不被外部直接访问
  • 继承(Inheritance):可以从已有的类创建新的类,重用代码
  • 多态(Polymorphism):不同对象可以以统一的方式被使用

代码示例:定义一个计算平均值的类

#include <iostream>
#include <vector>
using namespace std;

class Statistics {
private:
    vector<int> data;

public:
    void addData(int value) {
        data.push_back(value);
    }

    double calculateAverage() {
        if (data.empty()) return 0.0;
        int sum = 0;
        for (int val : data) {
            sum += val;
        }
        return static_cast<double>(sum) / data.size();
    }
};

int main() {
    Statistics stats;
    stats.addData(5);
    stats.addData(10);
    stats.addData(15);
    stats.addData(20);
    stats.addData(25);

    cout << "平均值是:" << stats.calculateAverage() << endl;

    return 0;
}

3. 比较一下:

 

二、引入与定义

1. 为什么需要类

面向对象编程中,类(Class)是创建对象的蓝图或模板。它定义了对象的属性(数据)和方法(行为)。通过类,可以创建多个具有相同属性和行为的对象

2. 类的定义

在C++中,类的定义使用class关键字

语法格式:

class 类名 {
    访问限定符:
        // 属性(成员变量)
        // 方法(成员函数)
};

代码示例:定义一个表示学生信息的类

#include <iostream>
using namespace std;

class Student {
public:
    // 属性
    string name;
    int age;
    double score;

    // 方法
    void introduce() {
        cout << "姓名:" << name << ", 年龄:" << age << ", 分数:" << score << endl;
    }
};

3. 类的成员

  • 成员变量(属性):保存对象的状态或数据,如nameagescore
  • 成员函数(方法):定义对象的行为或操作,如introduce()

三、访问限定符与封装

1. 访问限定符(入门篇也有)

访问限定符用于控制类的成员变量和成员函数的可见性。C++提供了三个访问限定符:

  • public(公有):公共成员,可以被类的内部和外部访问
  • private(私有):私有成员,只能被类的内部访问,外部不能直接访问
  • protected(受保护):受保护成员,可以被类的内部和子类访问,但无法被外部直接访问

2. 封装(Encapsulation)

封装是面向对象的基本特性之一,它将数据(属性)和操作数据的函数(方法)包装在一起,并对数据的访问进行控制,保护对象的完整性

3. 使用private进行封装

将类的成员变量设置为private,通过public的成员函数(如setget方法)来访问和修改数据

代码示例:

#include <iostream>
using namespace std;

class BankAccount {
private:
    string accountNumber;
    double balance;

public:
    // 构造函数
    BankAccount(string accNum, double bal) {
        accountNumber = accNum;
        balance = bal;
    }

    // 存款
    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            cout << "存款成功,当前余额:" << balance << endl;
        } else {
            cout << "存款金额必须大于0。" << endl;
        }
    }

    // 取款
    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            cout << "取款成功,当前余额:" << balance << endl;
        } else {
            cout << "取款金额不合法。" << endl;
        }
    }

    // 查询余额
    double getBalance() {
        return balance;
    }
};

int main() {
    BankAccount account("1234567890", 1000.0);
    account.deposit(500.0);
    account.withdraw(200.0);
    cout << "最终余额:" << account.getBalance() << endl;

    // account.balance = 5000.0; // 错误,无法访问private成员

    return 0;
}

4. 访问限定符的使用注意

  • 默认访问级别:如果未指定访问限定符,class中的成员默认是privatestruct中的成员默认是public
  • 建议:将成员变量设置为privateprotected,通过public成员函数访问,增强封装性

四、类的作用域

1. 类的成员作用域

  • 类的内部:可以访问所有成员,包括privateprotectedpublic
  • 派生类(子类):可以访问基类的protectedpublic成员,不能访问private成员
  • 类的外部:只能访问对象的public成员,不能访问privateprotected成员

2. 作用域解析符::

作用域解析符::用于指定变量或函数所属的作用域

代码示例:

#include <iostream>
using namespace std;

class Circle {
private:
    double radius;

public:
    Circle(double r);

    double getArea();
};

// 构造函数的实现
Circle::Circle(double r) {
    radius = r;
}

// 成员函数的实现
double Circle::getArea() {
    return 3.14159 * radius * radius;
}

int main() {
    Circle c(5.0);
    cout << "圆的面积是:" << c.getArea() << endl;
    return 0;
}

五、对象的实例化

1. 什么是实例化?

实例化(Instantiation)是根据类创建对象的过程。对象是类的具体实例,拥有类定义的属性和方法

2. 实例化对象的方法

  • 方式一:直接声明对象
ClassName objectName;
  • 方式二:使用new关键字在堆上创建对象,返回指针
ClassName* objectPtr = new ClassName();

代码实例:方式一

#include <iostream>
using namespace std;

class Rectangle {
public:
    double width;
    double height;

    double getArea() {
        return width * height;
    }
};

int main() {
    Rectangle rect; // 实例化对象
    rect.width = 10.0;
    rect.height = 5.0;
    cout << "矩形的面积是:" << rect.getArea() << endl;
    return 0;
}

代码示例:方式二

#include <iostream>
using namespace std;

class Rectangle {
public:
    double width;
    double height;

    Rectangle(double w, double h) {
        width = w;
        height = h;
    }

    double getArea() {
        return width * height;
    }
};

int main() {
    Rectangle* rectPtr = new Rectangle(10.0, 5.0); // 使用指针
    cout << "矩形的面积是:" << rectPtr->getArea() << endl;

    delete rectPtr; // 释放内存
    return 0;
}

 

六、对象大小的计算

1. 对象的内存布局

对象的大小与其成员变量有关(静态成员除外)。成员函数存在于代码段,多个对象共享同一份函数代码,因此不计入对象大小

2. 计算对象大小的方式

使用sizeof操作符可以获取对象或类的大小

语法:

sizeof(object);
sizeof(ClassName);

代码示例:

#include <iostream>
using namespace std;

class Example {
    char a;      // 1字节
    int b;       // 4字节
    double c;    // 8字节
public:
    void func() {}
};

int main() {
    Example e;
    cout << "对象e的大小:" << sizeof(e) << " 字节" << endl;
    cout << "类Example的大小:" << sizeof(Example) << " 字节" << endl;
    return 0;
}

注意:

  • 由于内存对齐,实际大小可能大于成员变量大小之和
  • 成员函数不影响对象大小

4. 分析内存对齐

#include <iostream>
using namespace std;

class Alignment {
    char a;    // 1字节
    // padding 3字节,使下一个int在4字节边界上
    int b;     // 4字节
};

int main() {
    cout << "类Alignment的大小:" << sizeof(Alignment) << " 字节" << endl;
    return 0;
}

解释:

  • char a占1字节,为了对齐,下一个int从第4字节开始,需要填充3字节
  • 总大小为1 + 3(填充) + 4 = 8字节

七、this指针

1. 什么是this指针?

this指针是C++中类的成员函数内的一个隐含指针,指向调用该成员函数的对象本身。通过this指针,可以在成员函数中访问对象的成员变量和其他成员函数

2. this指针的特点

  • 隐式存在:不需要显式声明,可直接使用
  • 指向当前对象:用于区分成员变量和形参或局部变量
  • 常用在返回对象自身或链式调用中

 代码示例

1.区分成员变量和形参

#include <iostream>
using namespace std;

class Person {
private:
    string name;
    int age;

public:
    void setName(string name) {
        this->name = name; // 使用this指针
    }

    void setAge(int age) {
        this->age = age;
    }

    void display() {
        cout << "姓名:" << name << ", 年龄:" << age << endl;
    }
};

int main() {
    Person person;
    person.setName("Bob");
    person.setAge(25);
    person.display();
    return 0;
}

2.返回对象自身,实现链式调用

#include <iostream>
using namespace std;

class Calculator {
private:
    int result;

public:
    Calculator() : result(0) {}

    Calculator& add(int value) {
        result += value;
        return *this;
    }

    Calculator& subtract(int value) {
        result -= value;
        return *this;
    }

    Calculator& multiply(int value) {
        result *= value;
        return *this;
    }

    int getResult() {
        return result;
    }
};

int main() {
    Calculator calc;
    int finalResult = calc.add(10).subtract(5).multiply(3).getResult();
    cout << "计算结果是:" << finalResult << endl;
    return 0;
}

3. const成员函数中的this指针

const成员函数中,this指针的类型为const ClassName*,表示不能修改对象的成员变量

#include <iostream>
using namespace std;

class Sample {
private:
    int value;

public:
    Sample(int v) : value(v) {}

    void display() const {
        // this指针的类型为 const Sample*
        cout << "值是:" << value << endl;
        // this->value = 10; // 错误,不能修改成员变量
    }
};

int main() {
    Sample s(5);
    s.display();
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mac|maven项目在idea中连接redis

安装maven brew install maven idea-setting导入redis插件 idea新建maven项目 构建系统选择maven 项目右侧数据库图标导入redis 新建一个数据库&#xff0c;名称必须为数字&#xff0c;测试一下是否可以连接&#xff0c;连接成功后选择确定 pom.xml导入redis <depende…

开发了一个成人学位英语助考微信小程序

微信小程序名称&#xff1a;石榴英语 全称&#xff1a;石榴英语真题助手 功能定位 北京成人学士学位英语辅助学习工具&#xff0c;包含记高频单词&#xff0c;高频词组&#xff0c;专项练习&#xff0c;模拟考试等功能。 开发背景 个人工作需要提高学习英文水平&#xff…

GitLab代码仓管理安装配置使用

Gitlab介绍 GitLab是一个基于Git的开源项目管理工具&#xff0c;它集成了版本控制、代码审查、持续集成&#xff08;CI&#xff09;/持续部署&#xff08;CD&#xff09;、自动化测试等多种功能&#xff0c;是一个完整的DevOps平台。以下是对GitLab的详细介绍&#xff1a; 一…

C# Retry库

比如网络访问或硬件参数设置需要重试&#xff0c;可引用gunet上的Polly库。 同步方式&#xff08;每次重试有不同的时间间隔&#xff09; var polly Policy.Handle<Exception>().WaitAndRetry(new[] { new TimeSpan(0, 0, 1), new TimeSpan(0, 0, 2), new TimeSpan(0, …

[论文阅读] Improved Baselines with Visual Instruction Tuning

启发&#xff1a; 1、LLaVA-1.5和LLaVA以及其他大模型相比&#xff0c;做出了哪些改进&#xff1f; &#xff08;1&#xff09;使用CLIP-ViT-L-336px作为视觉编码器&#xff0c;使模型能处理336px的高分辨率图像&#xff0c;这使得模型能从图像中提取出更多细节信息。此外&am…

动态规划,就这几个问题最高频!

目录 前言 什么是动态规划 连续子数组最大和 连续子数组最大乘积 最长递增子序列 最长公共子序列 最长公共子串 不同子序列 结语 【摘要】 前言大家好&#xff0c;我是bigsai&#xff0c;好久不见&#xff0c;甚是想念(天天想念)&#xff01;很久前就有小伙伴被动态规划…

迭代加深搜索、启发式搜索、A*、IDA

目录 回顾/本期梗概 一、迭代加深搜索&#xff08;IDDFS&#xff09; 1、IDDFS基础知识 1&#xff09;什么是迭代加深搜索 2)迭代加深的基本结构 3)IDDFS和BFS比较优势是什么 4&#xff09;IDDFS中的复杂计算问题 二、A*算法 1、A*算法基础知识 1.什么是A*算法 2.A*算法的核心…

102. UE5 GAS RPG 实现范围技能奥术伤害

在上一篇文章里&#xff0c;我们在技能蓝图里实现了通过技能实现技能指示&#xff0c;再次触发按键后&#xff0c;将通过定时器触发技能效果表现&#xff0c;最多支持11个奥术个体效果的播放。 在这一篇里&#xff0c;我们将实现技能播放时&#xff0c;对目标敌人应用技能伤害。…

Android OpenGL ES详解——裁剪Scissor

目录 一、概念 二、如何使用 1、开启裁剪测试 2、关闭裁剪测试 3、指定裁剪窗口&#xff08;位置和大小&#xff09; 4、裁剪应用举例 三、窗口、视⼝和裁剪区域三者区别 四、源码下载 一、概念 定义1&#xff1a; 裁剪是OpenGL中提⾼渲染的⼀种方式&#xff0c;只刷新…

内存马浅析

之前在jianshu上写了很多博客&#xff0c;但是安全相关的最近很多都被锁了。所以准备陆陆续续转到csdn来。内存马前几年一直是个很热门的漏洞攻击手段&#xff0c;因为相对于落地的木马&#xff0c;无文件攻击的内存马隐蔽性、持久性更强&#xff0c;适用的漏洞场景也更多。 J…

华为配置 之 GVRP协议

目录 简介&#xff1a; 配置GVRP&#xff1a; 总结&#xff1a; 简介&#xff1a; GVRP&#xff08;GARP VLAN Registration Protocol&#xff09;&#xff0c;称为VLAN注册协议&#xff0c;是用来维护交换机中的VLAN动态注册信息&#xff0c;并传播该信息到其他交换机中&…

62 mysql 中 存储引擎MyISAM 中索引的使用

前言 固定数据表 mysql. tables_priv 的表结构创建如下 CREATE TABLE tables_priv (Host char(60) COLLATE utf8_bin NOT NULL DEFAULT ,Db char(64) COLLATE utf8_bin NOT NULL DEFAULT ,User char(32) COLLATE utf8_bin NOT NULL DEFAULT ,Table_name char(64) COLLATE u…

局长们,今晚0点,国考抢考点!

2025国考报名确认已于11月1日0:00开始已经报完名且通过资格审核的小伙伴们一定要及时确认&#xff01; 具体流程是什么&#xff1f;操作时需要注意哪些事项&#xff1f;看完这篇就能全部搞定~ 25国考时间轴线 ✔️报名时间:10月15日8:00至10月24日18:00 ✔️审查时间:10月1…

list ------ 是一个带头双向循环的列表

结构 insert list 没有find&#xff0c;算法库有 #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<algorithm> #include<list> using namespace std; class Pos {int _row;int _col; public:Pos(int row, int col):_row(row),_col(col){c…

【已解决】【hadoop】如何解决Hive连接MySQL元数据库的依赖问题

在启动 Hive 之前&#xff0c;通常不需要手动连接到 MySQL 数据库。Hive 的配置文件 hive-site.xml 中已经包含了连接到 MySQL 元数据库所需的信息&#xff0c;包括用户名和密码。当你启动 Hive 服务时&#xff0c;Hive 会使用这些配置信息自动连接到 MySQL 数据库。 为什么还要…

react基础之redux快速上手环境准备

文章目录 核心概念配置基础环境提交action传参异步状态操作redux调试-devtools配套工具 Redux 是一个状态管理库&#xff0c;通常与 React 一起使用&#xff0c;帮助开发者管理应用的全局状态。它的核心理念是将应用的状态存储在一个单一的、不可变的状态树中&#xff0c;并通过…

YashanDB安装及使用问题和常用总结

在YashanDB的安装和使用中总会遇到一些问题&#xff0c;有些抓耳挠腮各种查&#xff0c;在此总结下遇到和群友问到的一些问题&#xff0c;和一些常用总结 一、官方文档 先附上官方文档地址&#xff0c;给迷路的小伙伴&#xff0c;官方文档整体还是比较简介易懂的 安装部署 |…

Unreal5从入门到精通之如何解决在VR项目在头显中卡顿的问题

前言 以前我们使用Unity开发VR,Unity提供了非常便利的插件和工具来做VR。但是由于Unity的渲染效果不如Unreal,现在我们改用Unreal来做VR了,所有的VR相关的配置和操作都要重新学习。 今天就来总结一下,我在开发VR过程中碰到的所有问题。 1.编辑器,以VR运行 默认运行方式…

C#与C++交互开发系列(十四):C++中STL容器与C#集合传递的形式

前言 在跨语言开发中&#xff0c;C 的 STL 容器&#xff08;如 std::vector, std::map&#xff09;和 C# 的集合类&#xff08;如 List<T>, Dictionary<TKey, TValue>&#xff09;之间的数据传递是一个常见需求。由于两者的内存布局和实现机制不同&#xff0c;直接…

docker离线安装达梦数据库

文章目录 下载达梦数据库docker镜像上传DM8镜像文件将DM8镜像导入到本地docker镜像仓库中查看本地docker镜像仓库是否存在DM8镜像带参数启动DM8docker启动DM8默认用户名/密码 下载达梦数据库docker镜像 达梦数据库官网 https://www.dameng.com/ 点击下载中心&#xff0c;选择D…