默认函数
C++11之前的问题
在C++11之前,如果给一个类显式地声明了构造函数(无论是默认构造函数还是自定义的),系统就不会再生成默认的抽象赋值函数和拷贝构造函数。这带来了一些不方便和隐藏的问题。举一个简单的例子:
#include <iostream>
class MyClass {
public:
MyClass() {}
~MyClass() {}
};
int main() {
MyClass obj1;
// MyClass obj2 = obj1; // 这里会报错:拷贝构造函数未声明
return 0;
}
在上述代码中,由于类中显式地声明了构造函数,系统就不再自动生成拷贝构造函数,致使实例化该类时存在问题。如果想要保留拷贝构造函数,必须显式地实现。
C++11中的默认函数特性
C++11中新增了default
关键字,用于显式说明一个类的构造函数、拷贝构造函数和赋值函数为“默认”。这样一旦需要,系统就会自动生成该函数,而不需要手动实现。
下面代码示例显示如何使用“默认函数”:
#include <iostream>
class MyClass {
public:
MyClass() = default; // 显式声明默认构造函数
MyClass(const MyClass&) = default; // 显式声明默认拷贝构造函数
~MyClass() = default; // 显式声明默认销毁函数
};
int main() {
MyClass obj1;
MyClass obj2 = obj1; // 正常使用拷贝构造函数
return 0;
}
以下例子展示了= default
的重要性,特别是在有继承关系时:
使用 = default
#include <iostream>
class Base {
public:
Base() = default;
Base(const Base&) = default;
virtual ~Base() = default;
};
class Derived : public Base {
public:
Derived() = default;
Derived(const Derived&) = default;
~Derived() = default;
};
int main() {
Derived d1;
Derived d2 = d1; // 正常使用默认的拷贝构造函数
return 0;
}
手动实现拷贝构造函数和析构函数
#include <iostream>
class Base {
public:
Base() {}
Base(const Base&) { }
virtual ~Base() { }
};
class Derived : public Base {
public:
Derived() {}
Derived(const Derived& other) : Base(other) {
}
~Derived() { }
};
int main() {
Derived d1;
Derived d2 = d1; // 使用手动实现的拷贝构造函数
return 0;
}
在没有default
关键字的情况下,我们需要手动为派生类实现拷贝构造函数和析构函数,否则编译器可能因为无法正确推导而导致错误或不期望的行为。通过显式使用= default
,我们可以确保派生类正确继承基类的行为,同时简化代码。
总结
在C++11中导入“默认函数”,是为了更简化和可控程序的设计。它解决了为了自定义函数而造成的隐藏问题,提高了程序的可读性和编写效率。对于需要增强控制的类,这一功能根据需要显式声明或撤销,是C++11重要的优化之一。