Для класса не существует конструктор по умолчанию с

Обновлено: 28.04.2024

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

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

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

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

Обратите внимание, что «конструктор по умолчанию» не является синонимом «конструктор, созданный компилятором». - Oliver Charlesworth

Конструктор по умолчанию создается всегда, но не всегда вызывается. Рассмотрим локальную переменную, которая не является константой, имеет тип POD и объявлена ​​без инициализатора. Объект выкован по памяти. Несмотря на то, что конструктор по умолчанию существует, он не вызывается для создания объекта. Члены данных имеют неопределенное значение. - David Hammen

9 ответы

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

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

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

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

ответ дан 20 авг.


Хм, это именно то, о чем я спрашивал. Не могли бы вы подтвердить то, что вы сказали "Under some circumstances a constructor won't be called, period" цитированием (стандартное или возможно дизассемблируемое). Затем я отмечу это как ответ (+1) - Самаурса

И чтобы убедиться, что я правильно понял . POD_type вы заявили, что можно использовать (позвонив POD_type.someVar ), но его члены не инициализируются, потому что отсутствуют функции-члены (конструкторы и т. д.) . правильно? - Самаурса

@Samaursa: ISO / IEC 14882: 2003 (E) раздел 8.5 параграф 9 (выделено мной): «Если для объекта не указан инициализатор, и объект имеет (возможно, cv-квалифицированный) тип класса (или массив), не относящийся к POD из этого), объект должен быть инициализирован по умолчанию; если объект имеет тип, определяемый константой, базовый тип класса должен иметь конструктор по умолчанию, объявленный пользователем. В противном случае, если для нестатического объекта не указан инициализатор, объект и его подобъекты, если таковые имеются, имеют неопределенное начальное значение.»- Дэвид Хаммен

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

Обратите внимание, что это имеет прямые практические последствия.

ответ дан 20 авг.


Итак, как только вы создаете экземпляр объекта, определяется и вызывается конструктор? А как насчет чистых структур C? Если у меня есть typedef struct A < int a; >A; , затем набрав A a; не генерирует конструктор (я думал, это определение структуры POD)? Почему в приведенном выше примере все по-другому? Просто потому, что мы сейчас имеем дело с C ++? - Самаурса

Компилятор всегда создает конструктор по умолчанию для класса POD. Не всегда им пользуется. - Дэвид Хаммен

@DavidHammen: Что вы имеете в виду под словом «генерирует»? Конструктор по умолчанию неявно объявляется только в том случае, если класс не имеет конструкторов, объявленных пользователем, и он определяется только в том случае, если он используется. - CB Бейли

@Charles: единственные объекты, которые не инициализируются через конструктор, - это объекты POD. Наличие объявленного пользователем конструктора означает, что класс не является POD. Компилятор всегда неявно объявляет конструктор по умолчанию при определении класса. Вопрос о том, определяет ли компилятор этот конструктор по умолчанию в это время, зависит от реализации. В любом случае, вы, ребята, упускаете суть, которая воплощена в словах если объект не требует инициализации. Объекты, не относящиеся к POD, всегда инициализируются. - Дэвид Хаммен

@DavidHammen: Первое предложение вашего комментария не соответствует действительности. Некоторые объекты типа класса, не относящиеся к POD, могут быть инициализированы через конструктор. Например, класс без каких-либо объявленных пользователем конструкторов может быть инициализирован значением, даже если он не является POD, а совокупные классы могут быть инициализированы с помощью предложения инициализатора, заключенного в фигурную скобку, которое также не использует конструктор, даже если совокупный класс не является POD . Кроме того, реализациям не разрешается определять неявно объявленный конструктор по умолчанию, если он не используется, что произойдет с инициализированными по умолчанию объектами, не относящимися к типу класса POD. - CB Бейли

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

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

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

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

ответ дан 20 авг.


Моим заголовком должно было быть «В каких случаях конструктора нет вообще, даже конструктора по умолчанию» - Самаурса

@Samaursa: Единственный раз, когда нет никакого конструктора, - это когда вы объявили какой-то конструктор, но не предоставили реализацию. Результат - непригодный для использования класс. Если, с другой стороны, вы не объявляете конструктор, компилятор (должен!) Создать конструктор по умолчанию от вашего имени. Вот что происходит с классом POD. В случае класса POD этот автоматически сгенерированный конструктор не вызывается при определенных обстоятельствах. Подробности смотрите в моем ответе. - Дэвид Хаммен

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

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

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

ответ дан 20 авг.

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

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

ответ дан 20 авг.

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

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

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

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

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

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

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

ответ дан 20 авг.

Вопрос относится к классам, для которых нет конструктор вызывается при создании экземпляра этого класса. Конструктор не вызывается для неглобальных, неконстантных переменных типа POD, объявленных без списка инициализаторов. Первоначальное содержание такого объекта неопределенно. Если вы объявляете конструктор, у вас больше нет класса POD, поэтому ваш пример - это не то, о чем спрашивал OP (и, конечно же, это не то, о чем писал автор этой электронной книги, на которую ссылается OP). - Дэвид Хаммен

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

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

введите сюда описание изображения

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

Ошибку выбивает в данной строке кода D4(int x, int y, int z, int i, int j, int u, int k) : D1(y, z), D3(i, j, u, k) < e = x; >Помогите, пожалуйста, разобраться с данной проблемой.

1 ответ 1

Во первых, по вашему рисунку иерархия должна строится так:

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

Так, как вы сделали, для конструирования объекта temp1 нужно конструировать D1 и D3 , а последный имеет виртуальный базовый класс D2 , а это значит, что любой целевой класс должен его конструировать, так как объект является один и тот же, но конструктор класса D4 не инициализирует D2 , поэтому вызывается его( D2 ) конструктор по умолчанию, которого просто нет(вы не написали). И не забывайте, что любой конструктор должен инициализировать члены класса, если они не инициализированы. Сохраняйте инвариант(свойство объекта иметь определенное состояние) всегда.

Если вам не трудно, то еще ответьте на один вопрос. Когда мы запускаем программу, то для B вызывается конструктор по умолчанию, а соответственно задается значение 0. Как сделать так, чтобы вызывался конструктор с параметрами и B задавалось значение последнего этапа цепочки ibb.co/JC2Bk7k

Я отсутствовал, но надеюсь теперь не поздно: в инициализаторе конструктора, в таком случаи, нужно указывать как должен конструироваться базовый класс, т. е. добавить, например, B(k) к списку

Не получается из-за того, что по сути нужно будет в D4 вызвать два раза B(z) и B(k), потому что он в цепочке отображается два раза, вот так, как я понял: D4(int x, int y, int z, int i, int j, int u, int k) : D1(y, z),B(z),D3(i,j,u,k),B(k) < e = x; >. Но все равно спасибо огромное вам за помощь.

Чтобы настроить, как класс инициализирует его члены или вызывать функции при создании объекта класса, определите конструктор. Конструкторы имеют имена, совпадающие с именами классов, и не имеют возвращаемых значений. Вы можете определить столько перегруженных конструкторов, сколько необходимо для настройки инициализации различными способами. Как правило, конструкторы имеют открытые специальные возможности, чтобы код за пределами определения класса или иерархии наследования может создавать объекты класса. Но вы также можете объявить конструктор как protected или private .

Конструкторы могут при необходимости принимать список инициализаторов элементов. Это более эффективный способ инициализации членов класса, чем назначение значений в тексте конструктора. В следующем примере показан класс Box с тремя перегруженными конструкторами. Последние два используют списки инициализации элементов:

При объявлении экземпляра класса компилятор выбирает, какой конструктор будет вызываться на основе правил разрешения перегрузки:

  • Конструкторы могут быть объявлены как inline , , explicitfriend или constexpr .
  • Конструктор может инициализировать объект, объявленный как const , volatile или const volatile . Объект становится const после завершения конструктора.
  • Чтобы определить конструктор в файле реализации, присвойте ему полное имя, как и любая другая функция-член: Box::Box() .

Списки инициализаторов элементов

При необходимости конструктор может иметь список инициализаторов элементов, который инициализирует члены класса перед запуском тела конструктора. (Список инициализаторов элементов не совпадает со списком инициализаторов типа std::initializer_list .)

Предпочитать инициализаторы элементов перечисляют значения вместо назначения значений в тексте конструктора. Список инициализаторов элементов напрямую инициализирует элементы. В следующем примере показан список инициализаторов элементов, состоящий из всех identifier(argument) выражений после двоеточия:

Идентификатор должен ссылаться на член класса; он инициализирован со значением аргумента. Аргумент может быть одним из параметров конструктора, вызова функции или . std::initializer_list

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

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

Конструкторы по умолчанию

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

Конструкторы по умолчанию являются одной из специальных функций-членов. Если конструкторы в классе не объявляются, компилятор предоставляет неявный inline конструктор по умолчанию.

Если используется неявный конструктор по умолчанию, обязательно инициализировать элементы в определении класса, как показано в предыдущем примере. Без этих инициализаторов члены будут неинициализированы, а вызов Volume() создаст значение мусора. Как правило, рекомендуется инициализировать элементы таким образом, даже если не используется неявный конструктор по умолчанию.

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

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

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

Это утверждение является примером проблемы "Большинство vexing Parse". Можно интерпретировать myclass md(); как объявление функции или как вызов конструктора по умолчанию. Поскольку средства синтаксического анализа C++ предпочитают объявления по сравнению с другими вещами, выражение рассматривается как объявление функции. Дополнительные сведения см. в разделе "Большинство синтаксического анализа".

Если объявлены какие-либо конструкторы, отличные от по умолчанию, компилятор не предоставляет конструктор по умолчанию:

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

Однако для инициализации массива объектов Box можно использовать набор списков инициализаторов:

Дополнительные сведения см. в разделе "Инициализаторы".

Конструкторы копии

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

Конструктор копирования может иметь одну из следующих сигнатур:

При определении конструктора копирования необходимо также определить оператор присваивания копирования (=). Дополнительные сведения см. в разделе "Назначение " и " Копирование конструкторов" и операторов присваивания копирования.

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

При попытке копирования объекта возникает ошибка C2280: попытка ссылаться на удаленную функцию.

Конструкторы перемещения

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

Компилятор выбирает конструктор перемещения, когда объект инициализируется другим объектом того же типа, если другой объект будет уничтожен и больше не нуждается в его ресурсах. В следующем примере показано одно дело, когда конструктор перемещения выбирается с помощью разрешения перегрузки. В конструкторе, который вызывает get_Box() , возвращаемое значение является xvalue (значение eXpiring). Поэтому он не назначается какой-либо переменной и поэтому выходит за пределы области действия. Чтобы обеспечить мотивацию для этого примера, давайте предоставим Box большой вектор строк, представляющих его содержимое. Вместо копирования вектора и его строк конструктор перемещения "крадет" его из значения "box", чтобы вектор теперь принадлежит новому объекту. Вызов std::move необходим, так как оба vector класса string реализуют собственные конструкторы перемещения.

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

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

Дополнительные сведения о написании конструктора нетривиального перемещения см. в разделе "Конструкторы перемещения" и "Операторы присваивания перемещения" (C++).

Явно заданные по умолчанию и удаленные конструкторы

Конструкторы копирования по умолчанию , конструкторы по умолчанию, конструкторы перемещения, операторы присваивания копирования, операторы присваивания перемещения и деструкторы. Вы можете явно удалить все специальные функции-члены.

Конструкторы constexpr

Конструктор может быть объявлен как constexpr , если

  • он либо объявлен как стандартный, либо удовлетворяет всем условиям для функций constexpr в целом;
  • класс не имеет виртуальных базовых классов;
  • каждый из параметров является литеральным типом;
  • тело не является блоком try-block функции;
  • инициализированы все нестатические члены данных и подобъекты базового класса;
  • Значение , если класс является (a) объединением, имеющим члены варианта, или (б) имеет анонимные объединения, инициализируется только один из членов профсоюза;
  • каждый нестатический член данных типа класса, а все подобъекты базового класса имеют конструктор constexpr.

Конструкторы списков инициализаторов

Затем создайте объекты Box следующим образом:

Явные конструкторы

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

Можно инициализировать Box следующим образом:

Или передать целое значение функции, принимающей объект Box:

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

Когда конструктор является явным, эта строка вызывает ошибку компилятора: ShippingOrder so(42, 10.8); . Дополнительные сведения см. в разделе о преобразованиях определяемых пользователем типов.

Порядок строительства

Конструктор выполняет свою работу в следующем порядке.

Вызывает конструкторы базовых классов и членов в порядке объявления.

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

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

Выполняет весь код в теле функции.

В следующем примере показан порядок, в котором конструкторы базовых классов и членов вызываются в конструкторе для производного класса. Сначала вызывается базовый конструктор. Затем члены базового класса инициализируются в том порядке, в котором они отображаются в объявлении класса. Наконец, вызывается производный конструктор.

Выходные данные будут выглядеть следующим образом.

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

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

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

Отменяется код в теле функции конструктора.

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

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

Производные конструкторы и расширенная инициализация агрегатов

Если конструктор базового класса не является открытым, но доступен для производного класса, нельзя использовать пустые фигурные скобки для инициализации объекта производного типа в /std:c++17 режиме, а затем в Visual Studio 2017 и более поздних версий.

В следующем примере показана соответствующая реакция на событие в C++14:

В C++17 Derived теперь считается агрегатным типом. Это означает, что инициализация Base через закрытый конструктор по умолчанию происходит непосредственно как часть расширенного правила агрегатной инициализации. Ранее частный Base конструктор был вызван через Derived конструктор, и он был успешно выполнен из-за friend объявления.

В следующем примере показано поведение C++17 в Visual Studio 2017 и более поздних версий в /std:c++17 режиме:

Конструкторы для классов с множественным наследованием

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

Должны выводиться следующие выходные данные:

Делегирующие конструкторы

Делегирующий конструктор вызывает другой конструктор в том же классе для выполнения некоторых действий по инициализации. Эта функция полезна, если у вас есть несколько конструкторов, которые все должны выполнять аналогичную работу. Основную логику можно написать в одном конструкторе и вызвать из других. В следующем тривиальном примере Box(int) делегирует свою работу Box(int,int,int):

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

Наследование конструкторов (C++11)

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

Visual Studio 2017 и более поздних версий: оператор using в /std:c++17 режиме и более поздних версиях преобразует все конструкторы из базового класса, за исключением тех, которые имеют идентичную сигнатуру конструкторам в производном классе. Как правило, рекомендуется использовать наследуемые конструкторы, когда производный класс не объявляет новые члены данных или конструкторы.

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

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

Конструкторы и составные классы

Классы, содержащие члены типа класса, называются составными классами. При создании члена типа класса составного класса конструктор вызывается перед собственным конструктором класса. Если у содержащегося класса нет конструктора по умолчанию, необходимо использовать список инициализации в конструкторе составного класса. В предыдущем примере StorageBox при присвоении типу переменной-члена m_label нового класса Label необходимо вызвать конструктор базового класса и инициализировать переменную m_label в конструкторе StorageBox :

У меня это происходит дважды в моем коде, я не уверен, почему он жалуется, что у меня есть файл заголовка "Scene.h":

У меня есть еще один файл с названием «InteractiveObject.h»:

Мой intellisense жалуется, что есть:

Ошибка 1 ошибка C2512: «InteractiveObject»: нет подходящего конструктора по умолчанию c: \ users \ james \ documents \ visual studio 2012 \ projects \ game \ game \ scene.h 26 1 Игра

Любые идеи с учетом того, что у обоих есть конструкторы по умолчанию?

Хорошо, спасибо всем присутствующим, я вижу, что если я сделаю это :;

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

Мое текущее требование состоит в том, чтобы сцена содержала определенное количество интерактивных объектов, объявленных в моем игровом конструкторе и повторяемых для вывода на экран:

Конструктор по умолчанию не требует передачи каких-либо аргументов либо потому, что он не принимает никаких аргументов, либо потому, что для всех названных параметров существуют значения по умолчанию. Из вашего кода требуются параметры конструктора класса InteractiveObject , но он также создается в вашем классе Scene , когда вы вызываете

Вы можете создать его динамически (используя new ) или добавить конструктор без аргументов в класс InteractiveObject .

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

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

Эти аргументы необходимо указать в объявлении объекта.

Он вызовет default constructor класса InteractiveObject . Однако предоставленный вами конструктор не соответствует default constructor , поскольку:

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

В ваших классах есть конструкторы не по умолчанию (то есть конструкторы, принимающие аргументы). У них нет конструкторов по умолчанию , которые не принимают никаких аргументов.

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

Ошибка: IntelliSense: не существует конструктора по умолчанию для класса «Blowfish» .

4 ответа

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

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

. так что ctor может быть вызван без (явного) указания алгоритма (в этом случае он будет использовать CBC в качестве алгоритма).

Другой альтернативой было бы явное указание алгоритма при определении объекта Blowfish:

В C ++ 11 (или новее) вам доступен еще один вариант. Вы можете определить свой конструктор, который принимает аргумент, но затем указать компилятору сгенерировать конструктор, который он имел бы, если бы вы его не определили:

В заключение, я думаю, стоит упомянуть, что ECB, CBC, CFB и т. Д. - это режимы работы, а не сами алгоритмы шифрования. Вызов их алгоритмов не беспокоит компилятор, но неоправданно вероятно вызовет проблемы для других, читающих код.

Вы объявили конструктор blowfish следующим образом:

Таким образом, эта строка не может существовать (без дальнейшей инициализации позже):

Поскольку вы не передали параметр. Он не понимает, как обрабатывать объявление объекта «BlowFish» без параметров - для этого нужно создать другой конструктор.

Конструктор по умолчанию - это конструктор, который либо не имеет параметров, либо, если он имеет параметры, все параметры имеют значения по умолчанию.

Потому что у вас есть это:

Это не конструктор по умолчанию . Конструктор по умолчанию - это тот, который не принимает параметров. т.е.

Читайте также: