对象的特征
对象的一些特性
感觉有用的就
- 构造函数和析构函数
- this指针
其他都是些细节
看构造函数和析构函数怎么写

1 #include <iostream> 2 using namespace std; 3 /*一个对象或者变量没有初始状态,对其使用后果是未知的 4 同样的使用完一个对象或变量,没有及时清理,也会造成一定的安全问题 5 6 C++利用构造函数和析构函数,这两个函数将会被编译器 7 自动调用,完成对象初始化和清理工作。对象的初始化 8 和清理工作是编译器强制要我们做的事情,因此如果我们 9 不提供构造和机构,编译器会提供。编译器提供的构造函数 10 和析构函数是空实现 11 12 构造函数:主要作用在于创建对象时为对象的成员属性赋值, 13 构造函数由编译器自动调用,无须手动调用 14 析构函数:主要作用在于对象销毁前系统自动调用,执行一些 15 清理工作。 16 17 */ 18 19 20 /* 21 构造函数语法:类名(){} 22 1、构造函数:没有返回值也不写void 23 2、函数名称与类名相同 24 3、构造函数可以有参数,因此可以发生重载 25 4、程序在调用对象时会自动调用构造函数, 26 无须手动调用,而且只会调用一次 27 */ 28 29 class Person{ 30 public: 31 Person(){ 32 cout<<"无参构造函数的调用"<<endl; 33 } 34 Person(int a){ 35 age=a; 36 cout<<"有参构造函数调用"<<endl; 37 } 38 ~Person(){ 39 cout<<"调用析构函数"<<endl; } 40 //拷贝构造函数 41 Person (const Person &p){ 42 age=p.age; 43 cout<<"拷贝构造函数"<<endl; 44 } 45 void setAge(int a){ 46 age=a; 47 } 48 int getAge(){ 49 return age; 50 } 51 private: 52 int age; 53 }; 54 55 56 /* 57 析构函数语法:~类名(){} 58 1、析构函数,没有返回值也不写void 59 2、函数名称与类名相同,在名称前加上符号~ 60 3、析构函数不可以有参数,因此不可以发生重载 61 4、程序在对象销毁前会自动调用析构,无须手动调用而且只会调用一次 62 */ 63 64 /* 65 构造函数的分类及调用 66 两种分类方法: 67 按参数分:有参构造和无参构造 68 按类型分:普通构造和拷贝构造 69 70 71 72 三种调用方式: 73 1、括号法 74 //Person p1;//默认构造函数调用 75 //Person p2(10);//有参构造函数 76 //Person p3(p2); //拷贝构造函数 77 注意:调用默认构造函数时,不要加() ,编译器会认为是一个函数声明 78 2、显示法 79 //Person p1; 80 //Person p2 = Person(10);//有参构造 81 //Person p3 = Person(p2);//拷贝构造 82 3、隐式转换法 83 Person p4=10;//相当于 Person p4 = Person(10); 84 85 */ 86 87 88 /* 89 拷贝构造函数调用时机 90 使用一个已经创建完毕的对象来初始化一个新对象 91 Person p1(10); 92 Person p2(P1); 93 值传递的方式给函数参数传值 94 void doWork(Person p) 95 { 96 97 } 98 void test02() 99 { 100 Person p; 101 doWork(p); 102 } 103 以值方式返回局部对象 104 Person doWork2() 105 { 106 Person p1; 107 return p1; 108 } 109 void test03() 110 { 111 Person p = doWork2(); 112 } 113 */ 114 //值传递的方式给函数参数传值 115 void doWork(Person p) 116 { 117 118 } 119 void test02() 120 { 121 Person p; 122 doWork(p); 123 } 124 //以值方式返回局部对象 125 Person doWork2() 126 { 127 Person p1; 128 return p1; 129 } 130 void test03() 131 { 132 // Person p = doWork2(); 133 cout<<doWork2().getAge()<<endl; 134 } 135 void test01() 136 { 137 Person p1;//调用无参构造函数 138 Person p2(10);//调用有参构造函数 139 Person p3(p2); 140 cout<<"p2.getAge(): "<<p2.getAge()<<endl; 141 cout<<"p3.getAge(): "<<p3.getAge()<<endl; 142 } 143 144 145 146 /*构造函数调用规则 147 1、默认构造函数(无参,函数体为空) 148 2、默认析构函数(无参,函数体为空) 149 3、默认拷贝构造函数,对属性进行值拷贝 150 如果写了拷贝构造函数就不会调用默认的 151 定义了有参构造函数,C++不再提供默认无参构造,但会提供默认拷贝构造 152 如果定义了拷贝构造函数,C++就不会提供其他构造函数 153 */ 154 //深拷贝与浅拷贝问题 155 /* 156 157 */ 158 159 int main() 160 { 161 // test01(); 162 // test02(); 163 test03(); 164 return 0; 165 }
初始化列表语法,作用同有参构造函数

1 #include <iostream> 2 using namespace std; 3 4 5 /* 6 C++提供了初始化列表语法,用来初始化属性 7 语法:构造函数():属性1(值1),属性2(值2),,, 8 */ 9 10 class Person 11 { 12 public: 13 // Person(int a,int b,int c){ 14 // m_A=a; 15 // m_B=b; 16 // m_C=c; 17 // } 18 Person(int a,int b,int c):m_A(a),m_B(b),m_C(c){ 19 } 20 int m_A; 21 int m_B; 22 int m_C; 23 }; 24 25 void test01() 26 { 27 Person p(1,2,3); 28 cout<<"p.m_A,B,C "<<p.m_A<<p.m_B<<p.m_C<<endl; 29 } 30 31 int main() 32 { 33 test01(); 34 return 0; 35 }
静态成员变量和静态成员函数

1 #include <iostream> 2 using namespace std; 3 4 5 //静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员 6 /*静态成员分为: 7 -静态成员变量 8 所有对象共享同一份数据 9 在编译阶段分配内存 10 类内声明,类外初始化 11 -静态成员函数 12 所有对象共享同一个函数 13 静态成员函数只能访问静态成员变量 14 */ 15 16 class Person{ 17 public: 18 //所有对象都共享同一份数据 19 //编译阶段就分配内存 20 //类内声明,类外初始化操作 21 static int m_A; 22 int m_B; 23 static void func(){ 24 cout<<"这是静态成员函数"<<endl; 25 cout<<m_A<<endl; //静态函数可以访问静态成员变量 26 // cout<<m_B<<endl; 错误的,静态函数不可访问非静态成员变量 27 } 28 }; 29 30 int Person::m_A=100; 31 32 void test01(){ 33 Person p1; 34 cout<<"p1.m_A="<<p1.m_A<<endl; 35 Person p2; 36 cout<<"p2.m_A="<<p2.m_A<<endl; 37 p2.m_A=200; 38 cout<<"p2.m_A=200后p1.m_A="<<p1.m_A<<endl; 39 cout<<"p2.m_A="<<p2.m_A<<endl; 40 41 } 42 void test02(){ 43 44 //静态成员变量有两种访问方式 45 //1、通过对象进行访问 46 //Person p; 47 //cout<<p.m_A<<endl; 48 //2、通过类名进行访问 49 cout<<Person::m_A<<endl; 50 51 } 52 53 void test03(){ 54 // 静态成员函数 55 //通过对象访问 56 Person p3; 57 p3.func(); 58 // 通过类访问 59 Person::func(); 60 } 61 62 int main() 63 { 64 // test01(); 65 // test02(); 66 test03(); 67 return 0; 68 }
看构造和析构调用顺序

1 #include <iostream> 2 using namespace std; 3 4 /*C++类中的成员可以是另一个类的对象,我们称该成员为对象成员 5 */ 6 class Phone{ 7 public: 8 Phone(string pName){ 9 m_PName=pName; 10 cout<<"Phone创建了"<<endl; 11 } 12 ~Phone(){ 13 cout<<"Phone消失了"<<endl; 14 } 15 string m_PName;//手机品牌名称 16 }; 17 18 class Person 19 { 20 public: 21 Person(string name,string pName):m_Name(name),m_Phone(pName){ 22 // m_Name=name; 23 // m_PName=pName; 24 cout<<"Person创建了"<<endl; 25 } 26 ~Person(){ 27 cout<<"Person消失了"<<endl; 28 } 29 string m_Name;//姓名 30 Phone m_Phone;//手机 31 }; 32 33 void test01() 34 { 35 Person p("张三","苹果"); 36 } 37 38 int main() 39 { 40 test01(); 41 return 0; 42 }
对象占多少内存的研究,只有非静态成员变量属于对象

1 #include <iostream> 2 using namespace std; 3 4 5 /* 6 在C++中,类内的成员变量和成员函数分开存储 7 只有非静态成员变量才属于类的对象上 8 */ 9 10 class Person{ 11 static int m_A; 12 }; 13 class Person1{ 14 int m_A; 15 static int m_B; 16 int func(){ 17 return m_A; 18 } 19 static void func2(){ 20 } 21 }; 22 23 void test01(){ 24 Person p; 25 // 空对象占用内存空间为1 26 //C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置 27 //每个空对象也应该有一个独一无二的内存地址 28 cout<<"size of p= "<<sizeof(p)<<endl; 29 // cout<<"id of p = "<<(int)p<<endl; 30 } 31 void test02(){ 32 // 非静态成员变量属于类的对象上 33 //p1有4个字节 34 //静态成员变量不属于类的对象上 35 Person1 p1; 36 cout<<"size of p1= "<<sizeof(p1)<<endl; 37 } 38 int main() 39 { 40 test01(); 41 test02(); 42 return 0; 43 }
this指针指向被调用的成员函数的所属对象

1 #include <iostream> 2 using namespace std; 3 4 /*this指针指向被调用的成员函数所属的对象 5 this指针是隐含在每一个非静态成员函数内的一种指针 6 this指针不需要定义,直接使用即可 7 8 this指针的用途: 9 1、解决名称冲突 10 当形参和成员变量同名时,可用this指针来区分 11 2、返回对象本身用*this 12 在类的非静态成员函数中返回对象本身,可使用return *this 13 */ 14 15 class Person{ 16 public: 17 Person(int age){ 18 // this指针指向被调用的成员函数所属的对象 19 this->age=age; 20 cout<<"age="<<age<<endl; 21 } 22 int age; 23 24 Person& PersonAddAge(Person &p) 25 { 26 this->age+=p.age; 27 //this指向p1的指针,而*this指向的就是p1这个对象的本体 28 return *this; 29 } 30 }; 31 32 void test01() 33 { 34 Person p(10); 35 } 36 37 void test02() 38 { 39 Person p1(10); 40 Person p2(10); 41 //链式编程思想 42 //但我感觉没啥用 p1.PersonAddAge(p2).PersonAddAge(p2).PersonAddAge(p2); 43 cout<<"p1.age="<<p1.age<<endl; 44 cout<<"p2.age="<<p2.age<<endl; 45 } 46 int main() 47 { 48 test01(); 49 test02(); 50 return 0; 51 }
空指针可以调用成员函数

1 #include <iostream> 2 using namespace std; 3 4 //C++中空指针也可以调用成员函数的,但是 5 //也要注意又没有用到this指针 6 //如果用到this指针,需要加以判断保证代码的 7 //健壮性 8 9 class Person{ 10 public: 11 void sayHello(){ 12 cout<<"HEllo"<<endl; 13 } 14 void showAge(){ 15 if(this==NULL)//可以保证代码的健壮性 16 { 17 return; 18 } 19 cout<<"m_Age="<<m_Age<<endl; 20 } 21 int m_Age=18; 22 }; 23 24 void test01() 25 { 26 Person *p=NULL; 27 p->sayHello(); 28 p->showAge(); 29 } 30 31 int main() 32 { 33 test01(); 34 return 0; 35 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现