相关文章推荐

C++ 构造函数有很多有意思的小细节。这里来做一些探讨。这些内容可能会分为几章,这一章来探讨 隐式构造函数,显式空构造函数 和 =default 修饰的构造函数 ,私有构造函数和 =delete 修饰的构造函数 之间的区别。

在开始之前,我们先了解两种特殊的类:

聚合类 与 POD

聚合类 是 C++ 中的一个特殊的类型。当一个类(class, struct, union) 满足以下条件时,它是一个聚合类:

  • 无显式声明的构造函数(可以是 default delete 的)
  • 无虚成员函数
  • 无私有的或受保护的非静态数据成员
  • 无使用 {} = 直接初始化的非静态数据成员
  • 一个普通数组也是一种聚合类型(如 int[10], char[], double[2][3])

    POD ( Plain old data structure ) 则是一种特殊的聚合类,它必须满足聚合类的所有条件,且不具有以下成员:

  • 指针到成员类型的非静态数据成员(包括数组)。
  • 非POD类类型的非静态数据成员(包括数组)。
  • 引用类型的(reference type)非静态数据成员。
  • 用户定义的拷贝与赋值算子。
  • 用户定义的析构函数。
  • 可见,POD类类型就是指class、struct、union,且不具有用户定义的构造函数、析构函数、拷贝算子、赋值算子;不具有继承关系,因此没有基类;不具有虚函数,所以就没有虚表;非静态数据成员没有私有或保护属性的、没有引用类型的、没有非POD类类型的(即嵌套类都必须是POD)、没有指针到成员类型的(因为这个类型内含了this指针)

    POD 一般用来在不同的模块之前传递数据使用。如一个 C++ 库向外提供 C 接口,可以使用 POD 作为参数。

    隐式构造函数,显式空构造函数 和 =default 修饰的构造函数。

    对于 未定义任何构造函数 的类型( struct class or union ),编译器会为该为自动生成一个 inline public 的构造函数, 如果这个类型满足 constexpr 类型的要求,则这个构造函数还会被 constexpr 修饰,这个由编译器生成的构造函数,我们称之为 隐式构造函数 或 默认构造函数。在 C++11 以前,如果用户声明了其它构造函数,则编译器不会生成默认构造函数,需要我们显式的声明。而在 C++11 以后,我们仍可用 default 关键字来强制编译器自动生成原本隐式声明的默认构造函数。

    在一般的C++类中,显式声明一个空方法体的构造函数和 default 构造函数、隐式构造函数没有什么区别。但是在聚合类(Aggregate classes)或POD(Plain old data structure)中,它们是不一样的。显式声明的构造函数会破坏类的聚合属性:拥有用户自定义构造函数的类不是聚合类。

    私有构造函数和 =delete 修饰的构造函数

    和上面一样,在一般类中,二者没有什么区别。但在聚合类中,私有的构造函数会破坏类的聚合属性。

    附 : 验证代码

    PeopleB pb0; //调用显式构造函数 PeopleB pb1{"Lucy", 16}; // ERROR PeopleB is not a aggregate type PeopleC pc0; PeopleC pc1{"Birdly", 3}; //聚合类初始化 PeopleD pd0{"MrLiu", 40}; //聚合类初始化 PeopleE pe0{"Lili", 16}; //非聚合类,无法调用聚合初始化方法 static_assert(std::is_pod<People>::value, "People is POD"); static_assert(std::is_pod<PeopleA>::value, "PeopleA is POD"); static_assert(!std::is_pod<PeopleB>::value, "PeopleB is NOT POD"); static_assert(!std::is_pod<PeopleC>::value, "PeopleC is NOT POD"); static_assert(!std::is_pod<PeopleD>::value, "PeopleD is NOT POD"); static_assert(std::is_pod<int[10]>::value, "an Array is POD"); return 0;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    #include <type_traits>
    //隐式构造函数。聚合类,POD
    struct People {
    const char * name ;
    int age ;
    } ;
    //default 构造函数。聚合类,POD
    struct PeopleA {
    PeopleA ( ) = default ;
    const char * name ;
    int age ;
    } ;
    //显式构造函数
    struct PeopleB {
    PeopleB ( ) { }
    const char * name ;
    int age ;
    } ;
    //聚合类,非POD
    struct PeopleC {
    int get_age ( ) { return age ; }
    ~ PeopleC ( ) { }
    const char * name ;
    int age ;
    } ;
    //delete 构造函数, 聚合类,非POD
    struct PeopleD {
    PeopleD ( ) = delete ;
    const char * name ;
    int age ;
    } ;
    //私有构造函数,非聚合类
    struct PeopleE {
    const char * name ;
    int age ;
    private :
    PeopleE ( ) { }
    } ;
    int main ( ) {
    People p0 ; //调用隐式构造函数
    People p1 { "LiLei" , 16 } ; //聚合类初始化
    PeopleA pa0 ; //调用 default构造函数
    PeopleA pa1 { "HanMeimei" , 16 } ; //聚合类初始化
    PeopleB pb0 ; //调用显式构造函数
    PeopleB pb1 { "Lucy" , 16 } ; // ERROR PeopleB is not a aggregate type
    PeopleC pc0 ;
    PeopleC pc1 { "Birdly" , 3 } ; //聚合类初始化
    PeopleD pd0 { "MrLiu" , 40 } ; //聚合类初始化
    PeopleE pe0 { "Lili" , 16 } ; //非聚合类,无法调用聚合初始化方法
    static_assert ( std : : is_pod < People > : : value , "People is POD" ) ;
    static_assert ( std : : is_pod < PeopleA > : : value , "PeopleA is POD" ) ;
    static_assert ( ! std : : is_pod < PeopleB > : : value , "PeopleB is NOT POD" ) ;
    static_assert ( ! std : : is_pod < PeopleC > : : value , "PeopleC is NOT POD" ) ;
    static_assert ( ! std : : is_pod < PeopleD > : : value , "PeopleD is NOT POD" ) ;
    static_assert ( std : : is_pod < int [ 10 ] > : : value , "an Array is POD" ) ;
    return 0 ;
    }
     
    推荐文章