В каких случаях вообще нет конструктора, даже конструктора по умолчанию? - PullRequest
7 голосов
/ 20 августа 2011

В этой книге Я сейчас читаю, я наткнулся на это:

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

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

РЕДАКТИРОВАТЬ: Я изменил заголовок, так как исходный заголовок дал значение, которое я спросил, когда был конструктор по умолчанию, не определенный вместо того, чтобы спрашивать, когда класс вообще не имеет конструктора.

Ответы [ 9 ]

6 голосов
/ 20 августа 2011

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

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

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

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

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

5 голосов
/ 20 августа 2011

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

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
3 голосов
/ 20 августа 2011

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

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

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

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

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

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

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

0 голосов
/ 30 января 2018

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

0 голосов
/ 14 сентября 2016

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

В некоторых случаях это делает компилятор. Некоторые из которых -

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

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

0 голосов
/ 12 января 2016

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

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

0 голосов
/ 21 августа 2011

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

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

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

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

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

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

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

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

0 голосов
/ 20 августа 2011

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

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

0 голосов
/ 20 августа 2011

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

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

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

...