为什么网站要改版,海拉尔做网站,网站内页优化,2021ppt模板免费下载 素材一、默认成员函数
1. 什么是默认成员函数#xff1f;
在C中#xff0c;每个类都有一些特殊的成员函数#xff0c;如果程序员没有显式地声明#xff0c;编译器会自动为类生成这些函数#xff0c;这些函数称为默认成员函数
2. 默认成员函数列表
默认构造函数#xff08…一、默认成员函数
1. 什么是默认成员函数
在C中每个类都有一些特殊的成员函数如果程序员没有显式地声明编译器会自动为类生成这些函数这些函数称为默认成员函数
2. 默认成员函数列表
默认构造函数Default Constructor默认析构函数Destructor默认拷贝构造函数Copy Constructor默认拷贝赋值运算符Copy Assignment Operator默认移动构造函数Move ConstructorC11引入默认移动赋值运算符Move Assignment OperatorC11引入
3. 编译器何时生成默认成员函数
显式声明如果程序员没有提供某个默认成员函数的定义编译器会根据需要自动生成特别注意一旦程序员显式地声明了任何一个拷贝或移动操作编译器将不会为该类生成移动操作需要手动提供
4. 代码示例
#include iostream
using namespace std;class Example {
public:int value;// 未显式声明任何默认成员函数
};int main() {Example ex1; // 调用默认构造函数ex1.value 10;Example ex2 ex1; // 调用默认拷贝构造函数Example ex3;ex3 ex1; // 调用默认拷贝赋值运算符cout ex1.value ex1.value endl;cout ex2.value ex2.value endl;cout ex3.value ex3.value endl;return 0;
}
二、构造函数
1. 什么是构造函数
构造函数Constructor是在创建对象时自动调用的特殊成员函数用于初始化对象的成员变量。构造函数的名称与类名相同
2. 特点
没有返回类型连void也没有可以有参数参数化构造函数支持函数重载即可以有多个构造函数可以在构造函数初始化列表中初始化成员变量
3. 默认构造函数
如果程序员未提供任何构造函数编译器会为类生成一个默认构造函数它对基本类型成员变量不进行初始化
4. 代码示例
1.默认构造函数
#include iostream
using namespace std;class Person {
public:string name;int age;// 默认构造函数Person() {name Unknown;age 0;}void display() const {cout 姓名 name , 年龄 age endl;}
};int main() {Person p; // 调用默认构造函数p.display();return 0;
}
2.参数化构造函数
#include iostream
using namespace std;class Person {
public:string name;int age;// 参数化构造函数Person(const string n, int a) {name n;age a;}void display() const {cout 姓名 name , 年龄 age endl;}
};int main() {Person p(Alice, 25); // 调用参数化构造函数p.display();return 0;
} 3.构造函数初始化列表
#include iostream
using namespace std;class Point {
private:int x;int y;public:// 使用初始化列表初始化成员变量Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {}void display() const {cout 坐标( x , y ) endl;}
};int main() {Point pt(3, 4);pt.display();return 0;
}
5. 注意事项
如果类中有const成员变量或引用类型成员必须使用初始化列表进行初始化构造函数可以被重载允许创建多个具有不同参数列表的构造函数
三、析构函数
1. 什么是析构函数
析构函数Destructor是在对象生命周期结束时自动调用的特殊成员函数用于释放对象占用的资源如内存、文件等。析构函数的名称是在类名前加上~符号
2. 特点
没有参数没有返回类型每个类只有一个析构函数不能重载编译器会自动调用析构函数无需手动调用
3. 代码示例
#include iostream
using namespace std;class Resource {
public:Resource() {cout 资源已分配。 endl;}~Resource() {cout 资源已释放。 endl;}
};int main() {cout 进入main函数。 endl;{Resource res; // 创建对象调用构造函数} // 离开作用域调用析构函数cout 退出main函数。 endl;return 0;
}
4. 在析构函数中释放资源
当类中使用了动态内存分配如使用new关键字需要在析构函数中释放内存防止内存泄漏
#include iostream
using namespace std;class Array {
private:int* data;int size;public:Array(int s) : size(s) {data new int[size];cout 数组已分配。 endl;}~Array() {delete[] data;cout 数组已释放。 endl;}
};int main() {Array arr(10);// 使用数组...return 0;
}
5. 注意事项
析构函数必须为公有成员函数否则对象在离开作用域时无法正确销毁避免在析构函数中抛出异常这可能导致程序不可预测的行为
四、拷贝构造函数
1. 什么是拷贝构造函数
拷贝构造函数Copy Constructor是使用同类的另一个对象来初始化新对象时调用的构造函数。它用于定义对象的拷贝行为
2. 语法
ClassName(const ClassName other);
参数为同类对象的引用通常为const引用避免不必要的拷贝
3. 默认拷贝构造函数
如果程序员未提供拷贝构造函数编译器会自动生成默认的拷贝构造函数执行浅拷贝对于没有动态内存分配的类默认的拷贝构造函数通常够用
4. 浅拷贝与深拷贝
浅拷贝Shallow Copy拷贝对象的成员变量值对于指针成员仅拷贝指针值两个对象指向同一内存位置深拷贝Deep Copy在拷贝指针成员时为新对象分配独立的内存空间并复制内容
5. 示例
1.默认拷贝构造函数浅拷贝
#include iostream
using namespace std;class Shallow {
public:int* data;Shallow(int val) {data new int(val);}~Shallow() {delete data;}
};int main() {Shallow obj1(5);Shallow obj2 obj1; // 调用默认拷贝构造函数cout obj1.data *(obj1.data) endl;cout obj2.data *(obj2.data) endl;// 修改obj1的数据*(obj1.data) 10;cout 修改obj1后 endl;cout obj1.data *(obj1.data) endl;cout obj2.data *(obj2.data) endl;return 0;
}
问题
由于是浅拷贝obj1和obj2的data指向同一内存当一个对象被析构时内存被释放另一个对象再使用时会导致悬空指针
2.自定义拷贝构造函数深拷贝
#include iostream
using namespace std;class Deep {
public:int* data;Deep(int val) {data new int(val);}// 自定义拷贝构造函数Deep(const Deep other) {data new int(*(other.data));}~Deep() {delete data;}
};int main() {Deep obj1(5);Deep obj2 obj1; // 调用自定义拷贝构造函数cout obj1.data *(obj1.data) endl;cout obj2.data *(obj2.data) endl;// 修改obj1的数据*(obj1.data) 10;cout 修改obj1后 endl;cout obj1.data *(obj1.data) endl;cout obj2.data *(obj2.data) endl;return 0;
}
6. 注意事项
拷贝构造函数的参数必须是引用否则会导致无限递归当类中有指针成员且需要独立的内存空间必须提供自定义的拷贝构造函数深拷贝
五、赋值运算符函数
1. 什么是赋值运算符函数
赋值运算符函数Assignment Operator Function用于定义对象间赋值行为operator。类似于拷贝构造函数它也需要考虑浅拷贝和深拷贝
2. 语法
ClassName operator(const ClassName other);
返回类型为引用返回当前对象自身*this以支持链式赋值参数为同类对象的**const引用**
3. 默认赋值运算符
如果程序员未提供赋值运算符函数编译器会生成默认的赋值运算符执行浅拷贝
4. 示例
1.默认赋值运算符浅拷贝
#include iostream
using namespace std;class Shallow {
public:int* data;Shallow(int val) {data new int(val);}~Shallow() {delete data;}
};int main() {Shallow obj1(5);Shallow obj2(10);obj2 obj1; // 使用默认赋值运算符cout obj1.data *(obj1.data) endl;cout obj2.data *(obj2.data) endl;// 修改obj1的数据*(obj1.data) 15;cout 修改obj1后 endl;cout obj1.data *(obj1.data) endl;cout obj2.data *(obj2.data) endl;return 0;
}
2.自定义赋值运算符函数深拷贝
#include iostream
using namespace std;class Deep {
public:int* data;Deep(int val) {data new int(val);}Deep(const Deep other) {data new int(*(other.data));}// 自定义赋值运算符函数Deep operator(const Deep other) {if (this other) {return *this; // 检查自赋值}delete data; // 释放原有内存data new int(*(other.data)); // 分配新内存并拷贝return *this;}~Deep() {delete data;}
};int main() {Deep obj1(5);Deep obj2(10);obj2 obj1; // 使用自定义赋值运算符cout obj1.data *(obj1.data) endl;cout obj2.data *(obj2.data) endl;// 修改obj1的数据*(obj1.data) 15;cout 修改obj1后 endl;cout obj1.data *(obj1.data) endl;cout obj2.data *(obj2.data) endl;return 0;
}
5. 注意事项
检查自赋值在赋值运算符函数中应检查this和other是否为同一对象避免释放自己释放原有资源在进行赋值前应释放对象原有的资源防止内存泄漏返回*this的引用支持链式赋值
六、const成员函数
1. 什么是const成员函数
const成员函数是指在函数声明后加上const关键字的成员函数表示该函数不会修改对象的成员变量除非成员变量被声明为mutable
2. 语法
返回类型 函数名(参数列表) const;
3. 特点
const成员函数只能调用其他const成员函数不能调用非const成员函数可以被const对象调用而非const成员函数不能被const对象调用
4. 代码示例
#include iostream
using namespace std;class Sample {
private:int value;public:Sample(int v) : value(v) {}int getValue() const {return value;}void setValue(int v) {value v;}
};int main() {const Sample s(10); // 常量对象cout 值是 s.getValue() endl;// s.setValue(20); // 错误不能调用非const成员函数return 0;
}
5. const对象和成员函数
**const对象**对象被声明为const只能调用其const成员函数不能修改成员变量**非const对象**可以调用所有成员函数包括const和非const
6. 成员函数重载
可以根据const性对成员函数进行重载 代码示例
#include iostream
using namespace std;class Example {
public:void func() {cout 非const版本的func() endl;}void func() const {cout const版本的func() endl;}
};int main() {Example e;e.func(); // 调用非const版本const Example ce;ce.func(); // 调用const版本return 0;
}
七、取地址及const取地址操作符重载
1. 取地址操作符operator
默认情况下对象的取地址操作会返回对象的内存地址。可以通过重载operator来改变取地址操作的行为
2. 为什么需要重载取地址操作符
在某些情况下我们希望隐藏对象的内部地址或提供特殊的地址计算方式可以用于智能指针的实现
3. 语法
ClassName* operator();
const ClassName* operator() const;
4. 示例
1.重载取地址操作符
#include iostream
using namespace std;class MyClass {
public:int value;MyClass(int v) : value(v) {}// 重载取地址操作符MyClass* operator() {cout 自定义取地址操作符被调用。 endl;return this;}// 重载const版本const MyClass* operator() const {cout 自定义const取地址操作符被调用。 endl;return this;}
};int main() {MyClass obj(10);MyClass* ptr obj; // 调用自定义取地址操作符cout value ptr-value endl;const MyClass cobj(20);const MyClass* cptr cobj; // 调用自定义const取地址操作符cout const value cptr-value endl;return 0;
}
5. 注意事项
小心使用重载取地址操作符可能导致代码难以理解和维护应该谨慎使用避免陷阱重载后可能会影响模板代码或标准库的使用需要确保兼容性