В каких случаях вообще нет конструктора, даже конструктора по умолчанию?

на книги в настоящее время я читаю, я наткнулся на это:

классу не нужен конструктор. Конструктор по умолчанию не требуется, если объект не нуждается в инициализации.

правильно ли я вывод из вышесказанного, что компилятор не генерирует конструктор по умолчанию для класса/структуры в некоторых случаях? Если да, то что это за дела? Я рискну и скажу, что под, вероятно, один из них. Есть ли другие?

EDIT: я изменил заголовок, поскольку исходный заголовок дал значение, которое я спросил, когда конструктор по умолчанию не определен, вместо того, чтобы спрашивать, когда класс вообще не имеет конструктора.

9 ответов


классу не нужен конструктор. Конструктор по умолчанию не требуется, если объект не нуждается в инициализации.

Я думаю, автор говорит об этой ситуации:

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

при некоторых обстоятельствах конструктор не будет вызываться, точка. Как только вы пишете конструктор, у вас нет класса POD, поэтому теперь конструктор будет вызван.

хорошо это или плохо, чтобы объект бегал вокруг этого содержит случайные, неинициализированные данные-это совсем другой вопрос.


конструктор по умолчанию всегда объявляется. Но она не всегда определена. Только если он используется, то компилятор (или) определить ее. Примеры:

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

Если вы всегда создаете объекты класса с помощью конструктора с параметрами, ему не понадобится конструктор по умолчанию.

компилятор генерирует конструктор по умолчанию для каждого класса, но если вы определяете свой собственный конструктор для этого класса, то компилятор не генерирует конструктор по умолчанию сам по себе. Пока вы создаете объекты такого класса с помощью предоставленного Вами конструктора, класс не будет нуждаться и иметь конструктор по умолчанию.

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;
}

In контексте приведенного выше примера, рассмотрим цитату из книги:

классу не нужен конструктор. Конструктор по умолчанию не требуется, если объект не нуждается в инициализации.

В приведенном выше примере, как объекта Myclass создается при использовании #1, класс не требует и имеет конструктор по умолчанию.

конструктор по умолчанию должен быть определен для класса, если объект Myclass создана таким образом, что нужен конструктор по умолчанию, i.e: #2.


на мой взгляд, это предложение означает, что вам не всегда придется писать свой собственный конструктор по умолчанию, так как некоторые классы не должны быть инициализированы по умолчанию.

например, если ваш класс содержит несколько полей класса, которые предоставляют свой собственный конструктор по умолчанию, вам не нужно писать конструктор по умолчанию, так как конструктор членов вызывается по умолчанию.

в крайнем случае наоборот, вы можете написать struct или class стручков для чего вы полагаетесь на программиста, чтобы правильно инициализировать свои поля вручную; в этом случае вы не можете написать конструктор по умолчанию, поэтому компилятор напишет свой собственный, который оставит эти поля по умолчанию неинициализированными значениями (на самом деле это будет no-op и, вероятно, будет оптимизирован).


компилятор только объявляет и определяет автоматически созданный конструктор по умолчанию, если вы не предоставили никакого конструктора.

с не инстанцируемый родительский класс однако можно предотвратить работу любого конструктора. Добавив фиктивный конструктор с фиктивным параметром, можно убить только автоматически сгенерированный конструктор по умолчанию, за счет большей волокиты.


в вашем вопросе есть определенная двусмысленность. Видите ли, неявные действия, которые компилятор выполняет в отношении конструкторов, включают оба объявления им и определение них. Если какой-то конструктор объявлен, но не определен, считаете ли вы, что он существует или нет?

в любом случае, нет способа создать класс, у которого нет конструкторов объявил для него. Конструктор копирования, например, всегда объявляется. Это невозможно. подавлять его. Если вы не объявите его сами, компилятор объявит его для вас.

что касается конструктора по умолчанию-можно подавить его неявное объявление. Если вы объявите любой конструктор самостоятельно (т. е. явно), компилятор не будет неявно объявлять значение по умолчанию. Но в этом случае ваш класс, конечно же, будет иметь конструктор: тот, который вы объявили сами. (Кроме того, как я сказал выше, конструктор копирования всегда объявленный.)

Что касается неявно определена конструкторы... Они определяются компилятором только в том случае, если вы их используете. И, конечно, они определяются только в том случае, если это возможно. (Если вы используете неявный конструктор, и его невозможно определить, то ваша программа просто не будет компилироваться).

Итак, еще раз, когда дело доходит до объявил конструкторы, невозможно иметь класс без конструкторов вообще. Любой класс имеет по крайней мере один конструктор объявлен для него.

Если вы заинтересованы в определена конструкторы в частности, тогда действительно возможно иметь класс, для которого не определен конструктор. Вот пример для вас

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

вот и все. Класс имеет один конструктор, объявленный в, но он не определен:)


конструктор по умолчанию не определен для класса, если другой конструктор объявляется.

для типов POD (в смысле тривиальности и стандартной компоновки, поскольку эти термины определены в C++11) является спорным вопросом, генерирует ли компилятор конструктор или нет, поскольку созданные компилятором конструкторы тривиальны. Для кровавых деталей, посмотрите на что такое агрегаты и стручки и как / почему они особенные?


проще говоря - (в контексте CPP) Если конструктор не определен, то компилятор не имеет конструктора по умолчанию. Он определяется компилятором только в том случае, если это необходимо.

есть определенные случаи, когда это делается компилятором. Некоторые из них ... --2-->

  1. когда у нас есть класс, который имеет объект базового класса в качестве члена (и конструктор производного класса не определен). В этом случае создается контруктор по умолчанию для производного класса, так как пролог из его contructor необходимо вызвать базовый класс contructor.
  2. у нас есть объект-контейнер. Ниже код объясняет это.

    class Legs
    {
    ctor(); // ctor stands for constructor
    };
    class cat
    {
    Legs leg;
    public:
    cat(){}
    };
    
  3. в случае виртуальных функций установка указателя виртуальной таблицы на правильную V-таблицу выполняется в конструкторе. По этой же причине конструктор по умолчанию будет определен компилятором.


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