先看下面代码
代码内容很简单,定义了一个包含成员x,y的类Point。在序列的地方可以使用这个类
虽然我们并没有定义Point类的构造函数,我们依然可以定义Point类的pt对象并使用它,其原因是编译器会自动生成一个缺省的构造函数,其效果相当于
但是,一旦添加了其他有参数的构造函数,编译器就不再生成缺省的构造函数了
C++11允许我们使用=default
来要求编译器生成一个默认构造函数:
这样,我们就可以继续我们的美好生活了。
#include
struct Point {
Point() = default;
Point(int _x, int _y) : x(_x), y(_y){}
int x;
int y;
};
int main() {
Point point;
printf("%d, %d", point.x, point.y);
}
如果是自己编写的无参构造函数的话,就需要指定成员的构造方式。默认构造函数会对数据成员进行默认初始化,不需要另外指定。这样可以省去一些麻烦。
由于整数是内置类型,而整数成员的默认初始化是不初始化,所以本例中的x,y还是需要类内初始化。这是另一个话题。
默认构造函数:是无参调用的构造函数,包括两种:
class Box {
public:
Box() { /*执行任何必需的默认初始化步骤*/}
//所有参数都有默认值
Box (int w = 1, int l = 1, int h = 1): m_width(w), m_height(h), m_length(l){}
...
}
默认构造函数在默认初始化和值初始化中得到调用。
说人话:如果构造函数在未指定参数或者提供了一个空初始化器列表,则会调用默认构造函数:
vector v1;
vector v2{};
默认构造函数是一种特殊的成员函数。如果未在类中声明任何构造函数,则编译器将提供隐式的inline默认构造函数
#include
using namespace std;
class Box {
public:
int Volume() {return m_width * m_height * m_length;}
private:
int m_width { 0 };
int m_height { 0 };
int m_length { 0 };
};
int main() {
Box box1; //调用编译器生成的构造函数
cout << "box1.Volume: " << box1.Volume() << endl; // Outputs 0
}
如果声明了任何非默认构造函数、编译器不会提供默认构造函数:
class Box {
public:
Box(int width, int length, int height)
: m_width(width), m_length(length), m_height(height){}
private:
int m_width;
int m_length;
int m_height;
};
int main(){
Box box1(1, 2, 3);
Box box2{ 2, 3, 4 };
Box box3; // C2512: no appropriate default constructor available
}
如果类中没有默认构造函数,将无法通过单独使用方括号语法来构造该类的对象数组。 例如,在前面提到的代码块中,框的数组无法进行如下声明:
Box boxes[3]; // C2512: no appropriate default constructor available
但是,可以使用一组初始值设定项列表来初始化 Box 对象的数组:
Box boxes[3]{ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
语法:
语法 | 说明 | o |
---|---|---|
类名 ( ) ; |
(1) | |
类名 :: 类名 ( ) 函数体 |
(2) | |
类名() = delete ; |
(3) | C++11起 |
类名() = default ; |
(4) | C++11起 |
类名 :: 类名 ( ) = default ; |
(5) | C++11起 |
其中 类名 必须指名当前类(或类模板的当前实例化),或在命名空间作用域或友元声明中声明时,必须是有限定的类名。 |
struct Point {
Point(){ x = 0; y = 0;};
int x;
int y;
};
struct Point {
Point(); //声明1
int x;
int y;
};
Point::Point(){
x = 10;
y = 0;
};
重载决议
所选择,则程序编译失败。struct Point {
Point() = delete ; // 错误:使用了被删除的函数‘Point::Point()’
int x;
int y;
};
#include
struct Point {
Point() = default;
Point(int _x, int _y) : x(_x), y(_y){}
int x;
int y;
};
int main() {
Point point;
printf("%d, %d", point.x, point.y);
}
struct Point {
Point() ; // 错误:使用了被删除的函数‘Point::Point()’
int x;
int y;
};
Point::Point() = default;
#include
struct Point1 {
int x;
int y;
};
class Point2 {
public:
int x;
int y;
};
union Point3 {
int x;
int y;
};
int main() {
Point1 point1;
Point2 point2;
Point3 point3;
printf("%d, %d\n", point1.x, point1.y);
printf("%d, %d\n", point2.x, point2.y);
printf("%d, %d\n", point3.x, point3.y);
}
#include
struct Point1 {
Point1() = default; // 必须,当用户最定义了有参构造函数时编译器不会自己生成默认构造函数
Point1(int _x, int _y) : x(_x), y(_y){}
int x;
int y;
};
class Point2 {
public:
Point2() = default; // 必须,当用户最定义了有参构造函数时编译器不会自己生成默认构造函数
Point2(int _x, int _y) : x(_x), y(_y){}
int x;
int y;
};
union Point3 {
Point3() = default; // 必须,当用户最定义了有参构造函数时编译器不会自己生成默认构造函数
Point3(int _x) : x(_x){}
int x;
int y;
};
int main() {
Point1 point1;
Point2 point2;
Point3 point3;
printf("%d, %d\n", point1.x, point1.y);
printf("%d, %d\n", point2.x, point2.y);
printf("%d, %d\n", point3.x, point3.y);
}
内置类型被认为具有默认构造函数和拷贝构造函数。但是,对于内置类型的未初始化的非static变量,其默认构造函数不会被调用。内置整数类型的默认值为0,浮点数默认值为0.0,指针类型的默认值为nullptr
void f(){
int a0; //未初始化
int a2{}; //初始化为0
double d1{}; //初始化欸0.0
char *p{}; //p变成nullprt
int *p1 = new int; //未初始化
int *p2 = new int{}; //初始化为0
}
内置类型的构造函数最常用于模板参数:
template<typename T>
struct Handle{
T * p;
Handle(T *pp = new T{}) :p{pp}{}
};
Handler<int> px; //会生成int{} --- 初始化为0
引用和const必须被初始化。因此,一个包含这些成员的类不能默认构造,除非程序员提供了类内成员初始化器或者定义了一个默认构造函数来初始化它们
int glob{9};
struct X{
const int a1{7}; //ok
const int a2; //错误:需要一个用户自定义构造函数
const int & r{9}; //ok
int& r1{glob}; //ok
int& r2; //错误,需要一个用户自定义构造函数
};
X x; //错误:X没有默认构造函数
class A
{
public:
A(); //没有参数
};
class B
{
public:
explicit B(int x = 1, bool b = true); //每个参数有初始值
//explicit:阻止执行隐式转换,但是可以显示类型转换
};
class C
{
public:
explicit C(int c); //非默认构造函数
};
struct A
{
int x;
A(int x = 1): x(x) {} // 用户定义默认构造函数
};
struct B: A
{
// 隐式定义 B::B(),调用 A::A()
};
struct C
{
A a;
// 隐式定义 C::C(),调用 A::A()
};
struct D: A
{
D(int y): A(y) {}
// 不会声明 D::D(),因为存在另一构造函数
};
struct E: A
{
E(int y): A(y) {}
E() = default; // 显式预置,调用 A::A()
};
struct F
{
int& ref; // 引用成员
const int c; // const 成员
// F::F() 被隐式定义为弃置
};
int main()
{
A a;
B b;
C c;
// D d; // 编译错误
E e;
// F f; // 编译错误
}
https://author.baidu.com/home?from=bjh_article&app_id=1597683592389912
等待研究