构造函数
是一种特殊的函数,主要用来在创建对象时初始化对象。
定义:
- 构造函数函数名和类名相同
- 构造函数没有返回值类型和返回值,void 都不能写,不能 return
- 构造函数可以重载,需要满足重载条件
之前用类里面的元素要先声明,然后调用函数初始化,用构造直接初始化
如果类对象创建是没有传递任何参数->调用无参的构造函数(类里不写任何构造函数编译器会自动创建一个无参构造函数)
构造函数在类对象创建的时候自动调用,无法在创建完成以后主动调用
#include <iostream>
#include <string>
class myString {
private:
char* buffer;//buffer n.缓冲器
public:
myString() {//无参构造函数
buffer = new char[2];
buffer[0] = ' ';
buffer[1] = '\0';
}
myString(int count, char ch) {//没有返回值,名字和类名相同
buffer = new char[count + 1];
int i = 0;
for (; i < count; i++) {
buffer[i] = ch;
}
buffer[count] = '\n';
}
void printf() {
std::cout << buffer << std::endl;
}
};
int main(){
std::string s(2, 'a');
myString s1;
myString s3(2, 'a');
myString* s2 = new myString(2, 'a');
s1.printf();
s2->printf();
}拷贝构造函数
拷贝构造函数是一种特殊的构造函数,是在定义一个新的对象时用自身这种类型的对象构造自身。通过同类型别的对象来初始化。
如果自己不写拷贝构造函数直接用,编译器给的拷贝构造函数是浅拷贝的。
一般拷贝构造函数都是深拷贝
myString(myString& other) {//拷贝构造函数
buffer = new char[strlen(other.buffer)+1];
int i = 0;//因为循环外要用到i,所以放外面
for(; i < strlen(other.buffer); i++) {
buffer[i] = other.buffer[i];
}
buffer[i] = '\0';
}深拷贝和浅拷贝
深拷贝就是只把值拷贝过来
浅拷贝是指向同一个地址
例如:以上的拷贝构造函数就是一个深拷贝
如果是浅拷贝函数体应该这样写:buffer = other.buffer
注意这个是对于指针类型的元素,如果是其他比如 int 那只能直接写 x=other.x,是深拷贝只拷贝值
析构函数
跟构造函数类似,也是一种特殊的函数,作用是对象结束生命周期时,系统自动调用析构函数来做清理工作
定义:
- 函数名与类名相同,在前面加上一个
即类名 (){} - 没有返回值类型和返回值,也没有参数
- 如果类中没有自己写析构函数,那么系统会给出一个隐式析构函数,什么也不做
this 指针
#include <iostream>
using namespace std;
class Person {
private:
string name; // 成员变量
int age;
public:
// 场景1:解决命名冲突 (最重要、最常用的场景!)
void setName(string name) { // 参数名和成员变量名相同
this->name = name; // 用 this-> 明确指出,等号左边是当前对象的name
}
void setAge(int age) {
this->age = age; // 等号左边是当前对象的age,右边是参数age
}
// 场景2:实现链式调用
Person& growUp() {//前面这个是返回类型,返回的是类引用,是调用对象本身,如果没有 &就是一个副本
this->age++; // 年龄+1
return *this; // 返回对象本身,注意返回引用才能连续操作同一个对象
}
void printInfo() {
// 其实这里编译器底层也是 cout << this->name << ...
// 但名字不冲突时,this-> 可写可不写,通常省略
cout << "Name: " << name << ", Age: " << age << endl;
}
};
int main() {
Person p1, p2;
// 使用 setName (解决命名冲突)
p1.setName("张三");
p1.setAge(20);
// 使用链式调用 (看起来非常流畅)
p2.setName("李四").setAge(18).growUp(); // 连续设置并让年龄增长一岁
p2.printInfo(); // 输出:Name: 李四, Age: 19
return 0;
}
作用:
- 解决传进来的形参和类自己的成员变量重名不好分辨的问题
- 实现链式调用
类成员变量初始化:fileNode(int value):a(value){}