1. 默认构造函数
没有参数的构造函数。
class Example {
public:
Example() {}
};
2. 带参数的构造函数
class Example {
public:
int value;
Example(int v) : value(v) {}
};
3. 拷贝构造函数
用于通过另一个同类型的对象来创建新对象。
它用于实现深拷贝,特别是当类包含指针成员。
class Example {
public:
int* value;
Example(int v) {
value = new int(v);
}
// 拷贝构造函数
Example(Example& other) {
value = new int(*(other.value));
}
};
4. 移动构造函数
用于通过转移资源来创建新对象,避免不必要的拷贝。
这里利用了右值引用。
class Example {
public:
int* value;
Example(int v) {
value = new int(v);
}
// 移动构造函数
Example(Example&& other) noexcept {
value = other.value;
other.value = nullptr;
//nullptr在C++11里表示空指针
}
};
提一下noexcept关键字,
noexcept告诉编译器,函数中不会发生异常。
如果在运行时,该函数向外抛出了异常,
(如果函数内部捕捉了异常并完成处理,这种情况不算抛出异常)
程序会直接终止。
5. 委托构造函数(C++11 引入)
一个构造函数可以调用同一个类中的另一个构造函数。
class Example {
public:
int value1;
int value2;
Example(int v1) : value1(v1), value2(0) {}
Example(int v1, int v2) : Example(v1) {
value2 = v2;
}
};
6. 默认成员初始化器(C++11 引入)
可以在类定义中为成员变量提供默认值。
这些默认值会被所有构造函数使用,除非在构造函数中显式初始化。
class Example {
public:
int value1 = 5;
int value2 = 10;
Example() {}
Example(int v1) : value1(v1) {
// value2 仍然使用默认值 10
}
};
7. 构造函数初始化列表
用于在构造函数的初始化列表中初始化成员变量。
对于常量成员、引用成员和没有默认构造函数的成员,必须使用这种方法。
class Example {
public:
const int value;
int& ref;
Example(int v, int& r) : value(v), ref(r) {}
};
8. 禁用构造函数(C++11 引入)
可以显式地删除构造函数,防止使用特定的构造函数。
class Example {
public:
Example() = delete; // 禁用默认构造函数
Example(int v) {}
};
9. 使用构造函数模板
构造函数也可以是模板,以允许不同类型的参数。
template<typename T>
class Example {
public:
T value;
Example(T v) : value(v) {}
};
typename
也可以用class
代替,两者在此处没有区别。
T 可以是任何类数据类型,关于模板就不在此多做赘述。
10.案例
下面做一个小综合案例,联系一下我的上篇文章 关于构造函数使用this指针的问题
#include <iostream>
#include <cstring>
class MenuItem {
public:
char name[50];
double price;
// 默认构造函数
MenuItem() : price(0.0) {
name[0] = '\0';
}
// 带参数的构造函数
MenuItem(const char* name, double price) : price(price) {
int i = 0;
while (i < sizeof(this->name) - 1 && name[i] != '\0') {
this->name[i] = name[i];
i++;
}
this->name[i] = '\0';
}
// 拷贝构造函数
MenuItem(const MenuItem& other) : price(other.price) {
strncpy(this->name, other.name, sizeof(this->name) - 1);
this->name[sizeof(this->name) - 1] = '\0';
}
// 委托构造函数
MenuItem(double price) : MenuItem("Unknown", price) {}
void display() {
std::cout << "商品: " << name << ", 价格: " << price << std::endl;
}
};
int main() {
MenuItem item1;
MenuItem item2("Pizza", 12.99);
MenuItem item3(item2);
MenuItem item4(9.99);
item1.display();
item2.display();
item3.display();
item4.display();
return 0;
}
ps:这段代码的strncpy函数如果报错,可以在第一行添加
#define _CRT_SECURE_NO_WARNINGS
禁用该警告。
警告的原因是你的编译器认为strncpy不安全。
你也可以这样写:
#include <iostream>
#include <cstring>
class MenuItem {
public:
char name[50];
double price;
// 默认构造函数
MenuItem() : price(0.0) {
name[0] = '\0';
}
// 带参数的构造函数
MenuItem(const char* name, double price) : price(price) {
strncpy_s(this->name, sizeof(this->name), name, _TRUNCATE);
}
// 拷贝构造函数
MenuItem(const MenuItem& other) : price(other.price) {
strncpy_s(this->name, sizeof(this->name), other.name, _TRUNCATE);
}
// 委托构造函数
MenuItem(double price) : MenuItem("Unknown", price) {}
void display() {
std::cout << "商品: " << name << ", 价格: " << price << std::endl;
}
};
int main() {
MenuItem item1;
MenuItem item2("Pizza", 12.99);
MenuItem item3(item2);
MenuItem item4(9.99);
item1.display();
item2.display();
item3.display();
item4.display();
return 0;
}
用strncpy_s规避该警告,但要注意的传参个数。