类中的特殊成员函数

类中的特殊成员函数

1、构造函数

1.1、命名

构造函数的名称必须与类名完全相同。构造函数的名称区分大小写,因此必须与类名的大小写完全匹配。

1.2、用途

初始化对象的成员变量。执行创建对象时所需的其他设置或计算。调用其他初始化方法1.3、生命周期

构造函数在对象创建时自动调用,且只调用一次。构造函数不是由程序员显式调用的,而是由语言的运行时环境在创建对象时自动调用。#include

#include

class Person {

private:

std::string name;

int age;

public:

//无参构造函数

Person() : name("Unknown"), age(0) {}

// 带参数的构造函数

Person(std::string name, int age) : name(name), age(age) {}

// 打印信息的方法

void printInfo() {

std::cout << "Name: " << name << ", Age: " << age << std::endl;

}

};

int main() {

Person person1;

person1.printInfo(); // 输出: Name: Unknown, Age: 0

Person person2("Alice", 30);

person2.printInfo(); // 输出: Name: Alice, Age: 30

return 0;

}

需要使用初始化列表的场景

当类中有引用成员时形参和成员属性同名当类中有const修饰的成员当类中存在其他类的子对象时#include

#include

class Person {

private:

std::string name;

int age;

public:

//无参构造函数

Person() : name("Unknown"), age(0) {}

// 带参数的构造函数

Person(std::string name, int age) : name(name), age(age) {}

// 打印信息的方法

void printInfo() {

std::cout << "Name: " << name << ", Age: " << age << std::endl;

}

};

int main() {

Person person1;

person1.printInfo(); // 输出: Name: Unknown, Age: 0

Person person2("Alice", 30);

person2.printInfo(); // 输出: Name: Alice, Age: 30

return 0;

}

2、析构函数

2.1作用

在对象的生命周期结束时被自动调用,用于执行清理工作,如释放对象所占用的资源(内存、文件句柄、网络连接等)。析构函数确保对象在销毁时不会导致资源泄露或其他问题。

2.2格式

~类名()

{}

2.3特性

自动调用:当对象超出其作用域(如局部对象),或者显式删除对象(如使用delete关键字删除动态分配的对象)时,析构函数会自动被调用。

不能被继承:析构函数不会被继承,每个类都必须有自己的析构函数(如果类中有资源需要清理)。

不能被显式调用:析构函数不能通过对象名或指针显式调用,只能由编译器自动调用。

没有返回类型和参数:析构函数没有返回类型,也不接受任何参数。

默认析构函数:如果一个类没有显式定义析构函数,编译器会提供一个默认析构函数,该析构函数什么也不做。然而,对于包含动态分配内存的类,通常需要定义自己的析构函数来释放这些内存。

2.4示例:

定义一个Person类,有const修饰的成员name;int成员age,char类型的成员sex,定义一个Stu类,包含Person 成员,double *成员,写出Person和Stu的构造和析构函数,每个类写出两种构造函数,实现一个公有的show函数,输出Stu类中属性和Person类中属性的值。

#include

using namespace std;

class Person

{

const string name;

int age;

char sex;

public:

//无参构造,初始化列表

Person():name("lisi"),age(14),sex('m') {}

//有参构造,初始化列表

Person(const string name, int age, char sex) :name(name), age(age), sex(sex)

{}

~Person()//析构函数

{}

void show()

{

cout << name << endl;

cout << age << endl;

cout << sex << endl;

}

};

class Stu

{

Person p1;

double* p2;

public:

Stu():p2(new double) {} //无参构造,初始化列表

//有参构造,初始化列表

Stu(const string name, int age, char sex, double score) :p1(name, age, sex), p2(new double(score))

{}

~Stu()//析构函数

{

delete p2;

}

void show()

{

p1.show();

cout << *p2 << endl;

}

};

int main()

{

//Stu s1;

//s1.show();

Stu s2("zhangsan", 20, 'm', 23.9);

s2.show();

return 0;

}

3、拷贝构造函数

3.1定义

用于创建一个新对象,并将其初始化为另一个同类型对象的副本

3.2格式

类名(const 类名 &other) //拷贝构造函数的参数是同类对象的引用

{}

3.3示例:

在2.4的基础上,写出Person类和Stu类的拷贝构造函数。

#include

#include

using namespace std;

class Person

{

const string name;

int age;

char sex;

public:

//无参构造,初始化列表

Person():name("lisi"),age(14),sex('m') {}

//有参构造,初始化列表

Person(const string name, int age, char sex) :name(name), age(age), sex(sex)

{}

~Person()//析构函数

{}

void show()

{

cout << name << endl;

cout << age << endl;

cout << sex << endl;

}

//拷贝构造函数

Person(const Person& other):name(other.name),age(other.age),sex(other.sex)

{

//name为常量字符串成员,在对象的生命周期内其值是不可修改,

// 应该在初始化列表中为常量成员变量赋值,这是C++中初始化常量成员的唯一途径

}

};

class Stu

{

Person p1;

double* p2;

public:

Stu():p2(new double) {} //无参构造,初始化列表

//有参构造,初始化列表

Stu(const string name, int age, char sex, double score) :p1(name, age, sex), p2(new double(score))

{}

~Stu()//析构函数

{

delete p2;

}

void show()

{

p1.show();

cout << *p2 << endl;

}

Stu(const Stu& other):p1(other.p1),p2(new double(*(other.p2)))

{

}

};

int main()

{

//Stu s1;

//s1.show();

Stu s2("zhangsan", 20, 'm', 23.9);

s2.show();

return 0;

}

3.4深浅拷贝

浅拷贝

浅拷贝是指创建一个新的对象,但新对象中的元素仍然是对原始对象中元素的引用。也就是说,浅拷贝只复制了容器本身,而不复制容器内部的元素。

深拷贝

深拷贝是指创建一个新的对象,并递归地复制它包含的所有对象,直到所有的元素都是新对象。这意味着深拷贝不仅复制了容器本身,还复制了容器内部的所有元素(以及这些元素内部可能包含的所有元素,依此类推)。

类中包含指针成员时,拷贝构造函数,让不同类对象中的指针成员指向相同的空间(浅拷贝),存在的问题:对于堆空间二次释放,资源抢占。系统默认提供的拷贝构造函数是浅拷贝。

何时发生深浅拷贝问题:

类中存在指针成员时,拷贝构造和拷贝赋值函数会发生深浅拷贝的问题

浅拷贝:两个不同类对象的指针成员,指向同一片空间,会造成资源抢占,析构释放多次的问题

深拷贝:两个不同类对象的指针成员,指向不同的空间,但是空间中存储的内容相同

4.拷贝赋值函数

4.1定义和功能

将一个对象的状态复制到另一个同类型的对象中。这个函数通常具有与类名相同的名称,并接受一个同类型的常量引用作为参数,同时返回对类对象的引用(通常带有const限定符,但在赋值操作符中不需要这样做,因为赋值操作本身会修改左侧对象)。

使用类对象给已有的类对象赋值时会自动调用拷贝赋值函数

4.2格式

类名 &operator=(const 类名 &other)

{

//函数体

}

4.3示例

在3.3的基础上完成拷贝赋值函数

#include

#include

using namespace std;

class Person

{

const string name;

int age;

char sex;

public:

//无参构造,初始化列表

Person():name("lisi"),age(14),sex('m') {}

//有参构造,初始化列表

Person(const string name, int age, char sex) :name(name), age(age), sex(sex)

{}

~Person()//析构函数

{}

void show()

{

cout << name << endl;

cout << age << endl;

cout << sex << endl;

}

//拷贝构造函数

Person(const Person& other):name(other.name),age(other.age),sex(other.sex)

{

//name为常量字符串成员,在对象的生命周期内其值是不可修改,

// 应该在初始化列表中为常量成员变量赋值,这是C++中初始化常量成员的唯一途径

}

//拷贝赋值函数

Person& operator=(const Person& other)

{

//const修饰的name成员无法被赋值

if (&other != this)

{

this->age = other.age;

this->sex = other.sex;

}

return *this;

}

};

class Stu

{

Person p1;

double* p2;

public:

Stu():p2(new double) {} //无参构造,初始化列表

//有参构造,初始化列表

Stu(const string name, int age, char sex, double score) :p1(name, age, sex), p2(new double(score))

{}

~Stu()//析构函数

{

delete p2;

}

void show()

{

p1.show();

cout << *p2 << endl;

}

//拷贝构造函数,调用其他类的拷贝构造函数时,也需要传同类引用

Stu(const Stu& other):p1(other.p1),p2(new double(*(other.p2)))

{

}

//拷贝赋值函数

Stu& operator=(const Stu& other)

{

if (&other != this)

{

//显性调用Person类的拷贝赋值函数,给Person类中的成员赋值

p1.operator=(other.p1);

*(this->p2) = *(other.p2);

}

return *this;

}

};

int main()

{

//Stu s1;

//s1.show();

Stu s2("zhangsan", 20, 'm', 23.9);

s2.show();

Stu s3 = s2;

s3.show();

return 0;

}

相关文章

365bet网上足球
小赢卡贷放款多久到账?大致时间是这样!
365取消提款
科普文章

科普文章

📅 07-04 👀 3619