一、构造函数
1、定义
-
构造函数是一种特殊的成员函数,它的名字与类名相同。它的主要作用是在创建类的对象时初始化对象的成员变量。
-
例如,对于一个
Student
类:
cpp
class Student
{
public:
int age;
string name;
Student(int a, string n) // 构造函数
{
age = a;
name = n;
}
};
当创建Student
对象Student stu(20, "Alice");
时,构造函数Student(int a, string n)
会被调用,将age
初始化为20,name
初始化为"Alice"
2、特点
- 函数名和类名 一样
- 没有返回值
- 创建对象的时候,自动调用
- 如果在设计一个类的时候, 没有手动添加构造函数,编译器会根据需要自动添加添加一个默认的无参构造函数如果自己添加了构造函数,编译器就不会再添加默认构造函数
- 构造函数不能用const修饰构造函数不能是虚函数
举例:
cpp
class Student{
public:
void Student();
void Student(const string &name,int age,int score);
Student();
Student(const string &name,int age,int score);
void playGame(const string &game);
void setName(const string &value);
void setAge(int value);
void setScore(int value);
private:
string name;
int age;
int score;
};
下面代码中哪些是构造函数?答案显而易见。
3、构造函数的分类
对拷贝构造函数重点说明:
cpp
Student(const Student& s){
}
1、拷贝构造函数的格式必须为 const String &s
2、浅拷贝和深拷贝
浅拷贝是指在拷贝对象时,只复制对象的成员变量的值,而不复制它们指向的动态分配的内存。对于指向动态内存的指针成员变量,浅拷贝会导致原始对象和拷贝对象共享同一块内存。
cpp
class ShallowCopy {
public:
int* ptr;
ShallowCopy(int value) {
ptr = new int(value);
}
ShallowCopy(const ShallowCopy& other) { // 浅拷贝构造函数
ptr = other.ptr; // 只复制指针
}
~ShallowCopy() {
delete ptr;
}
};
int main() {
ShallowCopy obj1(10);
ShallowCopy obj2 = obj1; // 调用浅拷贝构造函数
obj1.~ShallowCopy(); // 手动销毁obj1
// obj2现在持有一个悬挂指针,因为内存已经被释放
return 0;
}
深拷贝是指在拷贝对象时,不仅复制对象的成员变量的值,还复制它们指向的动态分配的内存。这意味着原始对象和拷贝对象各自拥有自己的内存副本。
cpp
class DeepCopy {
public:
int* ptr;
DeepCopy(int value) {
ptr = new int(value);
}
DeepCopy(const DeepCopy& other) { // 深拷贝构造函数
ptr = new int(*(other.ptr)); // 复制指针指向的值
}
~DeepCopy() {
delete ptr;
}
};
int main() {
DeepCopy obj1(10);
DeepCopy obj2 = obj1; // 调用深拷贝构造函数
obj1.~DeepCopy(); // 手动销毁obj1
// obj2仍然有效,因为它有自己的内存副本
return 0;
}
-
浅拷贝适用于对象没有动态分配内存或者动态内存可以通过其他方式管理的情况。
-
深拷贝适用于对象包含指向动态分配内存的指针,且需要确保拷贝的对象和原始对象完全独立的情况。
二、析构函数
1、析构函数是类的特殊成员函数,其名字是在类名前加~
。它在对象生命周期结束时被调用,用于释放对象占用的资源,如关闭文件、释放动态分配的内存等。
cpp
class String{
private:
char* str;
public:
String(const char* str=NULL);
~String();
void show(void);
};
String::~String(){
cout << "~String " << endl;
if(this->str){
delete [] this->str;
}
}
- 析构函数函数名是 在类名前面加上字符~
- 无参数无返回值(但有this指针)
- 一个类有且只有一个析构函数,所以肯定不能重载
- 如果没有手动添加析构函数, 编译器会根据需要提供一个默认的析构函数对象生命周期结束时,自动调用析构函数
- 析构函数不能用const修饰
特点
-
没有参数,不能重载。
-
如果用户没有定义析构函数,编译器会自动生成一个默认的析构函数,但默认析构函数不会做额外的资源释放操作。
三、普通成员函数
这是类中普通的成员函数,用于实现类的各种功能。它们可以访问类的成员变量
cpp
class Student
{
public:
int age;
string name;
void displayInfo()
{
cout << "Name: " << name << ", Age: " << age << endl;
}
};
displayInfo()
就是一个普通成员函数,它用于显示学生的姓名和年龄信息
四、静态成员函数
- 在类中用
static
关键字修饰的成员函数是静态成员函数。它属于类,而不是类的某个具体对象
cpp
class Student
{
public:
static int studentCount;
static void incrementCount()
{
studentCount++;
}
};
int Student::studentCount = 0;
五、友元函数
友元函数不是类的成员函数,但它可以访问类的私有(private
)和保护(protected
)成员。它是在类的定义中用friend
关键字声明的函数
cpp
class Student
{
private:
int age;
public:
Student(int a) : age(a) {}
friend void displayAge(Student s);
};
void displayAge(Student s)
{
cout << "Age: " << s.age << endl;
}
displayAge()
是Student
类的友元函数,它可以访问Student
类的私有成员变量age
特点:
-
友元函数不是类的成员函数,它没有
this
指针。 -
友元函数可以是普通函数,也可以是其他类的成员函数。