了解C++ 默默编写并调用哪些函数
先来看看一个空类
class Empty{
... }; // 空类
当有对象被创建出来并调用这些函数的时候 C++ 就会产出下面这些函数 :
class Empty {
public:
Empty(){
...}; //默认(default )构造函数
Empty(const Empty& params){
...}; // 拷贝(copy)构造函数
~Empty(){
...}; //析构函数
Empty& operator=(const Empty& params){
...}; // copy assignment 操作符
};
下面创建类的对象以及使用:
Empty e1; // 调用默认构造函数和析构函数
Empty e2(e1);// 调用copy构造函数
e2 = e1; // 调用 copy assignment 操作符
- copy 构造函数和 copy assignment 操作符,编译器创建的版本只会单纯地将来源对象的每一个 non-static 成员变量拷贝到目标对象。
下面来看看 copy 构造函数的用法
直接上代码:
#include<iostream>
template <typename T>
class Adg {
std::string _name;
T _value;
public:
Adg(const char* name, const T& value); // 声明构造函数
Adg(const std::string& name, const T& value); // 构造函数重载
};
template <typename T>
Adg<T>::Adg(const char* name, const T& value) {
// 定义构造函数
_name = name;
_value = value;
}
template <typename T>
Adg<T>::Adg(const std::string& name, const T& value) {
_name = name;
_value = value;
}
int main() {
Adg<int> no1("gwww", 2);
Adg<int> no2(no1); // 调用 copy 构造函数
return 0;
}
由于已经显式声明了构造函数,系统不再生成默认构造函数。
下面来看创建类的对象
Adg<int> no1("gwww", 2);
Adg<int> no2(no1); // 调用 copy 构造函数
- 由于 _name 的类型为 string, 所以第二条语句执行调用的是第二个为 string 类型的构造函数,并以 no1._name 和 no1._value 为实参进行 copy 构造完成初始化。
若进行如下操作:
Adg<int> no3 = no1; //调用 copy assignment 操作符
编译器为 Adg所生出的 copy assignment 操作符行为和 copy 构造函数的行为一样。
但有时候编译器会拒绝为 class 生出 operator=。
看代码
#include<iostream>
template <typename T>
class Adg {
std::string& _name; //改为了引用类型
const T _value; //加了const
public:
Adg(std::string& name, const T& value); // 构造函数重载
// 下面创建对象使用变量初始化 string 类型变量, 所以去掉了const
// 如果加上 const,两种初始化方式都可以
};
template <typename T>
Adg<T>::Adg(std::string& name, const T& value) : _name(name), _value(value) {
}
//上一条款提到了成员变量是const 或者 reference, 他们就一定需要初值,不能被赋值。
//也就是不能写成下面这样
/*
template <typename T>
Adg<T>::Adg(std::string& name, const T& value){
_name = name;
_value = value;
}
*/
int main() {
std::string newDog("gwww");
Adg<int> no1(newDog, 2);
Adg<int> no2(no1); // 正确,调用 copy 构造函数
no2 = no1; // 错误!
return 0;
}
从上面代码可以得出,当 no1._name 指向string对象 no1 时,不能通过 copy assignment 操作符改变 no1._name 所指的对象来指向 no2。不过调用 copy 构造函数不会出现这种情况。
当然,更改 const 成员也是不合法的。
- 最后请记住:
编译器可以暗自为 class 创建 default 构造函数、copy 构造函数、copy assignment 操作符,以及析构函数( 如果它们被调用的话)。