默认函数
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重要的优化之一。