当前位置: 首页 > news >正文

cpp学习笔记1--class

2年前学过cpp,但是一直没有用到,现在要读研了,终于要用到了,重新拿出来看一看,觉得很多东西都能在c和python上看到影子。

#include "iostream"
class Person {
private:std::string name;int age;public:// 默认构造函数Person() : name("Unknown"), age(0) { std::cout << "init 1" << std::endl; }// 带参数的构造函数Person(const std::string& n, int a) : name(n), age(a) { std::cout << "init 2" << std::endl; }// 拷贝构造函数Person(const Person& other) : name(other.name), age(other.age) { std::cout << "init 3" << std::endl; }// 析构函数~Person() {std::cout << name << "对象被销毁" << std::endl;}void introduce() {std::cout << "我叫" << name << ",今年" << age << "岁。" << std::endl;}void change(std::string new_name,int new_age) {name = new_name;age=new_age;std::cout << "changing is over" << std::endl;}
};

我来逐行解析一下。

首先私有变量是只有此类的此实例对象的公开区域的函数能调用的(后面还会有其他区域也能调用),也就是Person p1;Person p2;p2的pubilc函数不能调用p1的age,但是可以调用自己的,外部程序也无法直接访问age

Person p1;
Person p2;
p1.introduce();
p2.introduce();
p2.change("Trump", 72);//p2可以改变自己的age
p2.introduce();
p2.age=10;//错误用法

然后public的第一个构造函数。它相当于python里的self.init,是用来初始化私有变量的,name("unknown")就是给name赋值"unknown"。第一个初始化初始的是默认值,不需要传入参数,也不需要括号。而public的第二个带参数的构造函数就需要了,两者都只能初始化一次。

Person p1;
int x = 13;
std::string name = "Mike";
Person p2(name, x);
p2("x", 1);//常量、变量都可以,但不可重复初始化

我定义的这个name是string型,在构造函数里应该就是const std::string& n=name,这在c里是不合法的,因为n和name的类型不同,但在cpp里这表示拷贝,那n和name地址是否一样呢?验证一下

Person(const std::string& n, int a) : name(n), age(a) { std::cout << "init 2 "<<&n <<" " << &name << std::endl; }int x = 13;
std::string name = "Mike";
std::cout << &name << std::endl;
Person p1(name, x);

输出结果:

000000D8230FFA70
init 2 000000D8230FFA70 000000D8230FFA90

说明Person之前的name和Person里的n是同地址的,而Person里的n和name是不同的,这是因为第一个name是在main里定义的,第二个name是Person的一个private变量,改成std::string xname = "Mike";就好理解了。

接下来的拷贝构造函数是什么呢?如下图,很明显,它也是一个拷贝,那么&p3==&p4?当然不是。Person(const Person& other),&p3==&other是成立的,而p4是一个新创建的Person,所以地址不同,Person p4=p3,也是可以直接调用这个拷贝函数的。

int x = 13;
std::string name = "Mike";
Person p3(name, x);
Person p4(p3);
std::cout << "p3 address " << &p3 << std::endl;
std::cout << "p4 address " << &p4 << std::endl;

既然p3,p4地址都不同,那么拷贝之后再变化p3,p4也是不会跟着变化的。

同理我们可以直接如下使用拷贝,显然,p2=p1会调用之前构造的拷贝函数,但是&p3=p2不会,最后&p3==&p2,但不等于&p1

Person p1;
Person p2=p1;
Person &p3 = p2;
Person &p3 = &p2;//不符合拷贝用法,不能传入地址
std::cout << "p1 address " << &p1 << std::endl;
std::cout << "p2 address " << &p2 << std::endl;
std::cout << "p3 address " << &p3 << std::endl;

还有需要注意的是,初始化之后再改变x,p2的age也不会变。

int x = 13;
std::string name = "Mike";
Person p2(name, x);
p2.introduce();
x++;
p2.introduce();

最后是析构函数,是在Person的生命周期结束时自动调用的,也可以手动调用,会释放内存。它们是在栈区的,以p1,p2,p3创建 ,就会以p3,p2,p1自动释放。

Person p1;
Person p2=p1;
Person &p3 = p2;
std::cout << "p1 address " << &p1 << std::endl;
std::cout << "p2 address " << &p2 << std::endl;
std::cout << "p3 address " << &p3 << std::endl;
//p1.~Person();
p2.introduce();
p3.introduce();
p2.change("mike", 23);
p2.introduce();
p3.introduce();

而这个的p3和p2只会释放一次

相关文章:

  • 【QT】QT安装
  • Python生活手册-NumPy数组创建:从快递分拣到智能家居的数据容器
  • Springboot循环依赖
  • React-router v7 第八章(边界处理)
  • AI向量检索
  • DeepSeek提示词的技巧
  • URL混淆与权限绕过技术
  • Linux | WEB服务器的部署及优化
  • Doo全自动手机壳定制系统
  • 安全为上,在系统威胁建模中使用量化分析
  • 5G网络的安全挑战与应对策略:技术剖析与Python实战
  • 博图V20编译报错:备不受支持,无法编译。请更改为受支持的设备。
  • 解读《国家数据标准体系建设指南》:数据治理视角
  • [machine learning] Transformer - Attention (四)
  • Deepseek核心技术:模态穿透技术的实现原理与过程
  • 刷leetcodehot100返航版--哈希表5/5
  • OpenGl实战笔记(1)基于qt5.15.2+mingw64+opengl绘制三角形
  • Gradio全解20——Streaming:流式传输的多媒体应用(6)——构建视频流目标检测系统
  • Qt 信号槽机制底层原理学习
  • 安装SDL和FFmpeg
  • 媒体:南京秦淮区卫健委回应一医院涉嫌违规提供试管婴儿服务
  • 外交部发言人就澳大利亚联邦大选结果答记者问
  • 月薪3万文科友好,“AI训练师”真有那么赚?
  • 山东省委组织部办公室主任吴宪利已任德州市委常委、组织部部长
  • 全国台联原会长杨国庆逝世,享年89岁
  • 投资者建议发行优惠套票给“被套”小股东,张家界:将研究考虑