在哪些情况下根本没有构造函数,甚至是默认构造函数?

时间:2011-08-20 13:21:15

标签: c++ constructor default-constructor

在我this book正在阅读的内容中,我遇到了这个问题:

  

一个类不需要构造函数。如果对象不需要初始化,则不需要默认构造函数。

我是否正确地从上面推断出编译器在某些情况下不会为类/结构生成默认构造函数?如果是,那些案件是什么?我会冒险说POD可能就是其中之一。还有其他吗?

编辑:我更改了标题,因为原始标题的含义是我询问何时是未定义的默认构造函数,而不是询问类何时根本没有构造函数。

9 个答案:

答案 0 :(得分:5)

始终声明默认构造函数。但它并不总是被定义。只有在使用它时,编译器(或您)才能定义它。例子:

struct A { std::string str; };
// not yet defined

struct B : A { };
// not yet defined

B b; 
// Now B::B and A::A are defined

请注意,这会产生直接的实际后果

struct A { private: A(); };
struct B : A { };
// valid, as B::B is not yet defined

B b; 
// now invalid, because B::B is defined and tries to call a 
// private base class constructor

答案 1 :(得分:5)

  

一个类不需要构造函数。如果对象不需要初始化,则不需要默认构造函数。

我认为作者正在谈论这种情况:

some_type some_function () {
   POD_type this_is_intentionally_uninitialized;
   ...
}

在某些情况下,不会调用构造函数,句点。一旦你编写了一个构造函数,就没有POD类,所以现在将调用构造函数。

让一个包含随机,未初始化数据的对象运行是好还是坏是完全不同的问题。

答案 2 :(得分:3)

如果始终使用带参数的构造函数创建类的对象,则不需要默认构造函数。

编译器为每个类生成一个默认构造函数,但是如果为该类定义自己的构造函数,则编译器本身不会生成默认构造函数。只要您通过您提供的构造函数创建此类的对象,该类就不需要并具有默认构造函数。

class Myclass
{
    int m_i;
    public:
        Myclass(int i)
        {
            m_i = i;
        }

};

int main()
{
    Myclass obj1(10); // #1, uses overloaded constructor
    Myclass obj2; //#2, Will generate compiler error of no matching constructor
    return 0;
}

在上述示例的上下文中,请考虑本书中的引用:

  

一个类不需要构造函数。如果对象不需要初始化,则不需要默认构造函数。

在上面的示例中,只要使用#1创建Myclass的对象,该类就不需要并具有默认构造函数。

如果Myclass的对象是以需要默认构造函数的方式创建的,则需要为该类定义默认构造函数,即:#2。

答案 3 :(得分:0)

在我看来,这句话意味着你不必总是编写自己的默认构造函数,因为默认情况下可能不需要初始化某些类。

例如,如果您的类包含几个提供自己的默认构造函数的类字段,则不需要编写任何默认构造函数,因为默认情况下仍会调用成员的构造函数。

在极端相反的情况下,您可能希望编写一个structclass个POD,您依赖程序员手动初始化其字段;在这种情况下,您可能不会编写默认构造函数,因此编译器将自己编写,将这些字段保留为其默认的未初始化值(实际上,它将是无操作,并且可能会被优化掉)。

答案 4 :(得分:0)

如果您没有提供任何构造函数,编译器只会声明并定义一个自动生成的默认构造函数。

然而,使用non-instantiable parent class,可以防止任何类型的构造函数工作。通过添加一个带有伪参数的伪构造函数,可以仅杀死自动生成的默认构造函数,但代价是更多的繁文缛节。

答案 5 :(得分:0)

你的问题有些含糊不清。您可以看到,编译器对构造函数采取的隐式操作涉及声明它们和定义它们。如果声明了某个构造函数但未定义,那么您认为它是否存在?

无论如何,没有办法创建一个没有构造函数声明的类。例如,始终声明复制构造函数。没有办法压制它。如果你没有自己声明,编译器会为你声明它。

对于默认构造函数 - 可以抑制其隐式声明。如果您自己声明任何构造函数(即显式),编译器将不会隐式声明默认构造函数。但是在这种情况下,你的类当然会有一个构造函数:你自己声明的构造函数。 (另外,正如我上面所说,总是声明复制构造函数。)

至于隐式定义的构造函数......它们仅在您使用它们时由编译器定义。当然,只有在可能的情况下才会定义它们。 (如果使用隐式构造函数,并且证明无法定义,那么您的程序将无法编译)。

因此,再一次,当谈到声明的构造函数时,不可能有一个没有构造函数的类。任何类都至少为它声明了一个构造函数。

如果您对定义的构造函数特别感兴趣,那么确实可以有一个类,没有定义构造函数。这是你的一个例子

struct S {
  S(const S&);
};

就是这样。该类有一个构造函数声明它,但它没有定义:)

答案 6 :(得分:0)

如果声明了另一个构造函数,则没有为类定义默认构造函数。

对于POD类型(在平凡布局和标准布局的意义上,这些术语在C ++ 11中定义),编译器是否生成构造函数是一个没有问题的,因为编译器生成的构造函数是微不足道的。有关血腥的详细信息,请查看What are Aggregates and PODs and how/why are they special?

答案 7 :(得分:0)

如此简单地说 - (在CPP的背景下) 如果没有定义构造函数,那么编译器没有默认构造函数。 它仅在需要时由编译器定义。

在某些情况下,编译器会执行此操作。其中一些是 -

  1. 当我们有一个具有基类对象作为成员的类(并且未定义派生类构造函数)时。在这种情况下,创建派生类的默认构造函数是因为其构造函数的prolog需要调用基类构造函数。
  2. 我们有一个容器对象。下面的代码解释了这一点。

    class Legs
    {
    ctor(); // ctor stands for constructor
    };
    class cat
    {
    Legs leg;
    public:
    cat(){}
    };
    
  3. 如果是虚函数,则在构造函数中设置指向正确V表的虚拟表指针。出于这个原因,默认构造函数也将由编译器定义。

答案 8 :(得分:0)

some_type some_function(){    POD_type this_is_intentionally_uninitialized;    ... }