C++ class 是否具有默认构造函数以及在以下情况下调用哪些构造函数?

does a C++ class have default constuctor & what constructors are called in the following cases?

有些地方看的有点懵

我正在做这个例子page 假设有一本 class(Book),其中有一个对象(作者)作为其成员之一。这是构造函数:

Book::Book(string name, Author author, double price, int qtyInStock)
      : name(name), author(author) {   **// Must use member initializer list to construct object**
   // Call setters to validate price and qtyInStock
   setPrice(price);
   setQtyInStock(qtyInStock);
}

我试图在构造函数中声明对象作者而不是初始化程序 lisr。它给了我错误。 no matching function to call Author::Author() --> 这是 Author 的默认构造函数。


阅读这些 Whosebug 帖子后:this1 and 我的理解是,从那些 2 中总结:

所以从上面的所有内容来看,我的理解是 用户定义的 object/class 不会自动具有默认构造函数 ,这与基本类型不同。 这就是为什么它给出错误,如果我不使用成员初始化列表(调用复制构造函数),导致编译器尝试使用它(用户定义的 class)没有的默认构造函数来初始化它。

因此可能的解决方案是:为 class 定义一个默认构造函数,或者使用成员初始化器


然后我在 Whosebug 上读到这个 ​​post 说: "How Many default methods does a class have?" 答案提到 它有默认构造函数

1.如果它有默认构造函数,为什么我的第一个案例(书和作者 classes)会出错?

我也从这个 page 中读到,假设我之前定义了一个 class 点,然后页面写道:

Point p1;       // **Invoke default constructor**
                // OR Point p1 = Point(); NOT Point p1();

2。那么当我们像上面那样声明时,它是否调用了默认构造函数?如果是这样,为什么不报错?我以为 class 没有默认构造函数?

如果你能帮我澄清一下,并回答上面的两个问题(斜体),我将不胜感激

完整答案很大,在此呈现:

http://en.cppreference.com/w/cpp/language/default_constructor

如果你专门制作一个,总是有一个默认的构造函数。这包括可以接受但不必接受参数的构造函数 - 具有默认参数的构造函数和可变参数模板都可以是默认构造函数。

如果你把它标记为 = delete 那么它永远不会有。

否则,如果不存在用户提供的构造函数,编译器将尝试为您创建一个,除非在某些情况下(完全列在 上面的 link 隐式删除-声明的默认构造函数 节)

  • T 有一个没有默认初始值设定项的引用类型成员。

  • T 有一个 const 成员,没有用户定义的默认构造函数或默认成员初始值设定项 (C++11 起)。

  • T 有一个成员(没有默认成员初始值设定项)(C++11 起),它有一个已删除的默认构造函数,或者它的默认构造函数不明确或无法从此构造函数访问。

  • T 有一个直接的或虚拟的基础,它有一个删除的默认构造函数,或者它是不明确的或无法从这个构造函数访问。

  • T 有一个直接或虚拟基类,它有一个已删除的析构函数,或一个无法从此构造函数访问的析构函数。

  • T 是一个非联合 class,其变体成员 M 具有非平凡的默认构造函数,并且包含 M 的匿名联合的变体成员都没有默认成员初始值设定项。

以及联合类型的一些附加规则。

tl;dr:这很复杂。

并非为所有对象创建隐式默认构造函数。

主要规则是当一个对象没有任何类型的构造函数时,它会被分配一个隐式默认构造函数。

我不会详细介绍创建它们时规定的所有具体规则,您最好阅读 here

关于你关于错误信息的问题1:

I tried to declare the object author inside the constructor instead of initializer list. It gave me error.

您没有显示产生错误的代码,所以我假设它如下所示 - 如果我错了请纠正我。

// sample A - Bad code, wont compile
class Author { };
class Book
{
public:
    Book(int x, Author y): n(1) {
        a(y);  //-this line does NOT compile. 
               // initialization of a must be in the initializer list,
               // between :  and {
    }
private:
    Author a;
    int n;
};

上述代码无法编译的原因是语言规则规定,按值声明的嵌套对象必须以以下两种方式之一进行初始化: - 在初始化列表中 - 隐含地,通过让编译器调用默认构造函数 - 如果对象有默认构造函数,它将起作用。

最后,关于您的问题 2,是的,如果 class 有默认构造函数,Point 的示例声明确实会调用默认构造函数。同样,请参阅语言参考以阐明默认构造函数何时存在。