C++迈向精通,学习笔记:类与对象

C++:类与对象

注意,这是笔记,不是学习手册!!!有可能不适合别人阅读,如果读者有什么问题欢迎在评论区提问!!

类与对象

不要把类看的多么高深莫测,通过C语言中类型和变量的方式来类比记忆。

  • 类:类型
  • 对象:变量
  • 属性:数据
  • 行为:操作(函数)

在C++中,类可以看作一种自定义的类型,和C的结构体很像。
对于这个类,其中包含的每一个类型就是一个成员(结构体中的类型)也叫做类的属性,对于每个成员,都有可以对其进行操作的函数,这个函数就叫做成员方法,这个成员方法也叫做类的行为

例子:

对象
Catgarfield
Dogodie
Peoplehug

类是数据行为的集合。

定义类与使用:

class Cat{
};class Dog{
};class People{
};Cat garfield;
Dog odie;
People hug;

例子:

class People{// 属性string name;Day birthday;double height;double weight;void say(string word);void run(Location &loc);
}
/*************************************************************************> File Name: class.cpp> Author:Royi > Mail:royi990001@gmail.com > Created Time: Fri 23 Feb 2024 07:56:13 PM CST> Describe: ************************************************************************/#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <ctype.h>
#include <cmath>
#include <string>
#include <sstream>using namespace std;class People {
public:string name;unsigned int age;char sex;void say() {cout << "My name is " << name;cout << ", I'm " << age << "years old";if (sex == 'm') {cout << "I'm a boy!" << endl;} else {cout << "I'm a girl" << endl;}}  
};int main() {People hug;hug.name = "Captain Hu";hug.age = 40;hug.sex = 'm';hug.say();return 0;
}

类的作用

在程序设计时我们通过在类中规定一个值的界限而确定该对象的是否执行了合理的操作:

#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <ctype.h>
#include <cmath>
#include <string>
#include <sstream>using namespace std;class People {
public :void say() {cout << name << ", " << age << endl;}void set_name(string name) {this->name = name;return ;}void set_age(int age) { // 一个人的名字不能为负数if (age <= 0) {perror("Invalid parameters");exit(1);} else {this->age = age;return ;}}
private :string name;int age;
};int main() {People hug;hug.set_name("Royi");hug.set_age(40);hug.say();return 0;
}

访问权限

关键字作用(类外对类内)
public公告访问权限(所有人)
private私有访问权限(自己)
protected受保护的访问权限(自己和儿子)
friendly破坏私有(可以访问类内的类外方法)
  • 属性设置成private:只允许类内方法访问自己。

this

this是一个指针,这个指针指向当前对象。

构造/析构函数

构造/析构函数使用方式
默认构造函数People a;
People(string name);People a(“hug”);
People(const People &a)拷贝构造,与=不等价
~People();

类的定义与销毁

先运行对象的构造函数,执行完之后这个对象就算成立了。

当对象被销毁时,会调用析构函数。

在类中会有一个默认的构造函数,它没有任何参数(编译器添加)。

类只有在定义时才会调用构造函数。

有参构造和转换构造函数

  • 有参构造:在基础的构造函数中加入参数,调用时传入参数
  • 转换构造:只有一个参数的有参构造函数。给类提供了将其他类型的值隐式的转换为该类的方法

显式的类型转换:强制类型转换

隐式的类型转换:程序中看不见,是自动的

// ...
// 这是一个转换构造函数
A(int x) {cout << "transfer constructor" << endl;this->x = x;this->y = 0;
}// 调用时
void func(A a) {cout << "func :";a.output();return;
}// 如果调用
func(6);
// 也能通过编译,这种情况下就使用了隐式的类型转换,下面的代码也是转换构造:
A a = 4;
// 将4赋值给a类对象,调用的是转换构造

func(6) 函数在调用时实际上发生了这样的操作: func(A a = 6)

拷贝构造函数

传入相同类型的一个对象的引用时,将传入对象的值拷贝给当前对象。

//下面是一个拷贝构造函数
A(const A &a) {cout << "copy constructor";this->x = a.x;this->y = a.y;
}int mian() {
A a; // 调用的a类的默认构造函数
A b = a, c; // 调用的b类的拷贝构造函数,调用的是c类的默认构造函数
c = a; // 没有调用构造函数,使用了c的赋值运算符符号,但是需要重载
}

注意:只有定义类时,才会调用构造函数

为什么拷贝构造函数一定要传入const类型的值?

假设我们有一个 const 类型的类 const A a , 如果:

int mian() {const A a;A b = a; // 调用了拷贝构造,会报错
}

因为 const A 表示“不能变”,但是 & 表示可以变,逻辑冲突。

为什么拷贝构造一定要传入引用?

假设有这样的一行代码:

A c = a;

我们期望调用 c 的拷贝构造函数,但是如果 c 的拷贝构造函数中传入的不是引用,将会是下面的结果:

// 相当于将外部的a对象拷贝给参数列表中的a对象
A(const A = a) {...
}

这将会再次调用参数 A 对象的拷贝函数,这样会发生递归。

构造函数与析构函数的具体执行流程

第一原则

先构造的后析构。(先构造的对象有可能被后后构造的对象所依赖)

类中属性的构造顺序和当前类的构造顺序

初始化列表

故名思意,先给该类中的属性进行初始化。

class C{
public:// 初始化列表C(string n) : ch = 'a', a(n + ".a"), b(n + ".b") {name[this] = n;name.output(this, " class C constructor");}char ch;A a, b;~C() {name.output(this, " class C destructor");}
}

属性的构造顺序和当前类的构造顺序

属性先构造,本身对象再构造。(保证对属性的操作可执行)

属性的构造顺序与初始化列表的顺序无关。

属性的构造顺序只与属性的声明顺序有关。

使用初始化列表的原则

初始化列表的使用顺序与声明顺序应当相同。

代码:

展示了不同的方式定义的析构函数的用法:

constructor.cpp

#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <ctype.h>
#include <cmath>
#include <string>
#include <sstream>using namespace std;class A;
class MyMap : public map<A *, string> {
public :void output(A *p, string s) {if (find(p) == end()) {cout << "unknown name " << p;} else {cout << operator[](p);}cout << s << endl;return ;}
} name;class A {
public :A() {name.output(this, " default constructor");}A(int x) {name.output(this, " transfer constructor");this->x = x;this->y = 0;}A(const A &a) {name.output(this, " copy constructor");this->x = a.x;this->y = a.y;}A(int x, int y) {name.output(this, " 2 arguments constructor");this->x = x;this->y = y;}void operator=(const A &a) {name.output(this, " operator=");this->x = a.x;this->y = a.y;return ;}void output() {cout << "(" << x << ", " << y << ")" << endl;}~A() {name.output(this, " destructor");}
private:int x, y;
};void func(A a) {cout << "func : ";a.output();return ;
}namespace copy_constructor {int main() {const A d;A a;A b = a, c = d;name[&a] = "a";name[&b] = "b";name[&c] = "c";cout << "c = a" << endl;c = a;cout << "a = " << &a << endl;cout << "b = " << &b << endl;cout << "b = " << &c << endl;return 0;
}}namespace test1 {
int main() {A a(3, 4), b(3), c = 4;a.output();b.output();func(a);func(b);cout << "=========" << endl;func(6);return 0;
}
}
int main() {//test1::main();copy_constructor::main();return 0;
}

下面这个代码解释了构建与释放顺序

constructer_order.cpp:

#include <iostream>
#include <algorithm>
#include <list>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <ctype.h>
#include <cmath>
#include <string>
#include <sstream>using namespace std;class MyMap : public map<void *, string> {
public :void output(void *p, string s) {if (find(p) == end()) {cout << "unknown name " << p;} else {cout << operator[](p);}cout << s << endl;return ;}
} name;class A {
public :A(string n) {name[this] = n;name.output(this, "class A constructor");}~A() {name.output(this, "class A distructor");}
};class B {
public :B(string n) {name[this] = n;name.output(this, " class B constructor");}
};int main() {A a("a"), b("b");return 0;
}

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

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

相关文章

GB/T 35513.2-2017 聚碳酸酯PC模塑和挤出材料检测

聚碳酸酯塑料是一种无味、无臭、无毒、透明的无定形热塑型材料&#xff0c;是分子链中含有碳酸酯的一类高分子化合物的总称。 GB/T 35513.2-2017聚碳酸酯PC模塑和挤出材料测试项目 测试项目 测试标准 熔体体积流动速率 GB/T 3682 拉伸弹性模量 GB/T 1040.2 屈服应力 GB…

基于SSM的土家风景文化管理平台(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的土家风景文化管理平台&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spri…

使用Barrier对齐ConstraintLayout几个控件的最高的一个

前提就是想让一个控件X&#xff0c;对齐A&#xff0c;B&#xff0c;C等控件最高的位置&#xff0c;直接看图。 看&#xff0c;由于name的一行&#xff0c;或者2行&#xff0c;会导致email行的高度&#xff0c;可能比image块高&#xff0c;也可能比image快矮。 那么&#xff…

如何与施耐德Schneider建立EDI连接?

EDI基础知识 何为EDI&#xff1f;是一个软件、系统还是一种流程呢&#xff1f;准确来说&#xff0c;EDI全称Electronic Data Interchange&#xff0c;中文名称是电子数据交换&#xff0c;也被称为“无纸化贸易”。EDI是&#xff1a; 标准化的数据格式连接业务系统间的数据桥梁…

支持开源欧拉openEuler!米尔基于海思Hi3093核心板上市!

新品播报&#xff01;米尔电子发布了基于海思Hi3093高性能MPU的MYC-LHi3093核心板及开发板, 此款核心板支持openEuler embedded OS欧拉系统&#xff0c;丰富生态&#xff0c;可实现100%全国产自主可控。不仅如此&#xff0c;米尔基于Hi3093的核心板及开发板&#xff0c;配套提供…

谷歌浏览器调用相同url数据不刷新

原代码 原因 谷歌浏览访问相同接口默认调用缓存数据 解决方案 添加时间戳

算法打卡day25|回溯法篇05|Leetcode 491.递增子序列、46.全排列、47.全排列 II

算法题 Leetcode 491.递增子序列 题目链接:491.递增子序列 大佬视频讲解&#xff1a;递增子序列视频讲解 个人思路 和昨天的子集2有点像&#xff0c;但昨天的题是通过排序&#xff0c;再加一个标记数组来达到去重的目的。 而本题求自增子序列&#xff0c;是不能对原数组进行…

面试算法-69-三角形最小路径和

题目 给定一个三角形 triangle &#xff0c;找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 1 的两个结点。也就是说&#xff0c;如果正位于当前行的下标 i &#xff0c;那…

NSSCTF Round#11 Basic ez_signin

题目&#xff1a; from Crypto.Util.number import * from secret import flagp getPrime(512) q getPrime(512) assert p > q n p*q e 65536 m bytes_to_long(flag) num1 (pow(p,e,n)-pow(q,e,n)) % n num2 pow(p-q,e,n) c pow(m,e,n)print("num1",num1…

智慧城市的发展趋势与挑战:未来展望

随着信息技术的飞速发展&#xff0c;智慧城市已成为现代城市发展的重要方向。智慧城市通过集成应用先进的信息通信技术&#xff0c;实现城市管理、服务、运行的智能化&#xff0c;为城市的可持续发展注入了新的活力。然而&#xff0c;在智慧城市的发展过程中&#xff0c;也面临…

hadoop namenode 查看日志里面报错8485无法连接

一、通过日志排查问题&#xff1a; 1、首先我通过jpsall命令查看我的进程&#xff0c;发现namenode都没有开启 2、找到问题后首先进入我的日志目录里查看namenode.log [rootnode01 ~]# /opt/yjx/hadoop-3.3.4/logs/ [rootnode01 ~]# ll [rootnode01 ~]# cat hadoop-root-nam…

云农场种植、领养、收获,认养模式新浪潮

​ 小编介绍&#xff1a;10年专注商业模式设计及软件开发&#xff0c;擅长企业生态商业模式&#xff0c;商业零售会员增长裂变模式策划、商业闭环模式设计及方案落地&#xff1b;扶持10余个电商平台做到营收过千万&#xff0c;数百个平台达到百万会员&#xff0c;欢迎咨询。 在…

基于Springboot的疫情物资管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的疫情物资管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

Redis中的缓存雪崩

缓存雪崩 &#x1f914;现象分析 缓存雪崩是指在同一时段大量的缓存key同时失效或者缓存服务(Redis等)宕机&#xff0c;导致大量请求到达数据库&#xff0c;带来巨大压力。 &#x1f44a; 解决方案 利用Redis集群提高服务的可用性&#xff0c;避免缓存服务宕机给缓存业务添…

GZ083 产品艺术设计赛题第十

全国职业院校技能大赛 产品艺术设计赛项赛题十 赛项名称 产品艺术设计 英语名称 Product Art Design 赛项编号 GZ083 归属产业 数字产业 任务名称 “绣羽鸣春”鸟形象主题文具收纳袋设计 赛项组别 中职组 高职组 □学生组 □教师组 □师生联队试点赛项 R学生组 …

如何添加超时机制

在Arduino或其他嵌入式系统中添加超时机制可以确保系统不会无限期地等待某个事件或响应。超时机制通常用于串行通信、传感器读取或任何需要等待外部输入的场景。以下是如何在Arduino代码中实现超时机制的方法&#xff1a; (1)使用millis()函数&#xff1a; millis()函数返回从A…

PyTorch Lightning 与 TensorBoard 问题解决文档

PyTorch Lightning 与 TensorBoard 问题解决文档 🛠️ 简介 本文档旨在总结在使用 PyTorch Lightning 进行深度学习模型训练和使用 TensorBoard 进行训练过程可视化时遇到的常见问题及其解决方案。 问题及解决方案 问题 1: 远程训练与本地可视化 描述: 在远程服务器上使…

【Hadoop】使用Scala与Spark连接ClickHouse进行数据处理

风不懂 不懂得 叶的梦 月不听 不听闻 窗里琴声意难穷 水不见 不曾见 绿消红 霜不知 不知晓 将别人怎道珍重 落叶有风才敢 做一个 会飞的梦 孤窗有月才敢 登高在 夜里从容 桃花有水才怕 身是客 身是客 此景不能久 &#x1f3b5; Tie Yann (铁阳)、薄彩生《…

gofly框架api接口请求合法性验证

验证说明 api接口请求头带合法性参数&#xff0c;用来验证客户端请求是否来自自己授权的应用发起&#xff0c;这个防止api接口被第三方盗用&#xff0c;影响系统性能及数据安全。 服务端配置 配置文件在&#xff1a;resource/config.yaml&#xff0c;配置参数为app:下的apis…