Error c2512 нет подходящего конструктора по умолчанию

Обновлено: 04.05.2024

Я пытаюсь реализовать карточную игру на языке c++ с помощью VS-2013, и у меня есть класс "Player". Класс "Player" является абстрактным в том смысле, что никакие фактические объекты того класса не должны инициализироваться. Вместо этого он лишь там наследоваться на 4 разных класса игрока (с 4 разными игровыми стратегиями) - "PlayerType1" на "PlayerType4".

Это мой файл Player.h:

А это мой файл Player.cpp:

Я получаю следующие ошибки:

Всего 4 ошибки того типа, каждая указывающая на конструкторы PlayerType1 на PlayerType4.

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

Так же должен упомянуть у меня в проекте есть другой класс ("Card" класс) который является абстрактным и как раз там наследоваться другими классами ("FigureCard" и "NumericCard"), и так же не имеет конструктора, а производные классы имеют свои конструкторы, и это не вызывает никакой ошибки. Разницу я увидеть не могу.

Я поискал другие вопросы, но все они относятся к случаям в которых не был определен конструктор по умолчанию, и была предпринята попытка инициализации того класса в другом месте кода. Это не мой случай так как я не инициализирую объект класса "Player", только 4 производных класса.

Пожалуйста помогите! Заранее благодарю.

2 ответа

Даже если ваш класс Player является абстрактным, вы должны определить конструктор, потому что ваш класс имеет члены. Когда вы создаете экземпляр производного класса (любого вашего PlayerType) класса, он вызовет конструктор базового класса. Именно так работает наследование.

В том случае сделайте его protected (сделав его публичным было бы бесполезно в любом случае, потому что это чисто виртуальный класс).

Ваш класс Player имеет член private: const string name; . Посмотрите на ваш класс Card ; я держу пари он не имеет такого члена. Вот и разница.

Все дело в том, член const string name; должен как-то быть инициализирован, а так как он private , то он должен быть инициализирован в пределах класса Player . (Правила языка запрещают инициализацию приватного члена класса из производного класса.) Поэтому класс Player должен иметь конструктор который будет инициализировать член name . Пустой конструктор этого добивается.

Я не понимаю. Я смотрел на код в течение трех часов и я не вижу проблемы.

класс, который я создаю, называемый TwoDayPackage, является производным от класса Package.

вот как я определил конструктор:

вот как я реализую конструктор:

вот как я использую его в своей основной функции.

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

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

или каждый аргумент должен иметь значение по умолчанию.

тем не менее, точка Дирка о синтаксисе верна; если вы хотите вызвать родительские классы ctor, вы должны сделать это после этого двоеточия.

ответ@dirkgently показывает правильный синтаксис, но давайте немного расширим его. У тебя их два. классы

и затем вы приходите, чтобы определить его

. но это не работает? Почему? В принципе, потому что то, что вы говорите C++, не имеет смысла: Package::Package просто называет ctor суперкласса и ничего с ним не делает. Вы можете создать новый объект пакета класса, используя новая оператор

но это все еще не то, что вы хотите сделать; то, что вы хочу сказать C++ для contruct части пакета TwoDayPackage, используя этот список arg. Вам не нужно иметь полное имя, потому что компилятор уже знает, что родительского класса.

вы также можете просто назначить значения в дочернем ctor, но это неэффективно, так как это заставляет компилятор генерировать код для "нескольких поездок к колодцу". Таким образом, C++ имеет специальный синтаксис, где инициализаторы помещаются после двоеточия, как показал Дирк.

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

ответ таков:dirkgently. Объяснение-это последовательность инициализации в C++.

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

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

Затем он используется в std::vector std::pair следующим образом:

Применение

Попытка оттолкнуть вектор:

Ошибка компиляции (VS2008 SP1)

Заметки

std::vector документация говорит, что он должен принимать копируемые объекты и копируемые объекты:

T must meet the requirements of CopyAssignable and CopyConstructible (until C++11).

Код отлично компилируется с gcc и VS2008 (до SP1).

Вопрос

Что вызывает ошибку? Есть ли ошибка в VS2008 SP1? Если да, то каковы обходные пути?

Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату.

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

Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей.

Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.

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

Ответы 1

TL; DR

Это ошибка в VS 2008 SP1. Простейшим возможным обходным решением является предоставление конструктора по умолчанию при обнаружении VS 2008 SP1.

Объяснение

Проведя небольшое исследование, я обнаружил, что ветка на форуме msdn описывает похожую ситуацию. В ветке есть ответ от сотрудника Microsoft, который дает четкое объяснение.

Вот цитата (сокращенная для краткости, выделено мной):

  1. Give foo a default constructor. This will fast-swap the wstring and general-swap the foo.
  2. Give foo a default constructor, and a swap() implementation that can be picked up through ADL. This will fast-swap both the wstring and the foo.
  3. Write your own pair. This will disable the "Swaptimization".
  4. Use vector, wstring> > . This will fast-swap the shared_ptr and wstring . Of course, now you're doing more dynamic memory allocations, so this is desirable only in certain circumstances.

Обход

После рассмотрения обходных путей я выбрал №1: предоставление конструктора по умолчанию, если обнаружен VS2008 SP1:

Другие вопросы по теме

Позволяет ли Visual Studio 2008 сохранять рабочие области (наборы файлов открытого кода и их порядок)

Можно ли сделать так, чтобы унаследованный / настраиваемый элемент управления (WinForms) автоматически появлялся в панели инструментов VisualStudio после добавления ссылки на его DLL?

Здравствуйте, SVV, Вы писали:

SVV>Привет, всем.

SVV>Есть такой код:
SVV>

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


SVV>В результате ошибка компиллятора: error C2512: 'CA' : no appropriate default constructor available
SVV>Ошибка пропадает, если использовать конструкторы без параметров (или только СА без параметров). Как правильно переопределить конструкторы с параметрами?

Здравствуйте, SVV, Вы писали:
.

SVV>А двоеточие означает что конструктор СВ наследует код CA
ни в коем случае (см. ниже)

SVV>. или всего лишь определяет какой базовый конструктор вызывать

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

SVV> . если явного вызова не будет?
Если явного вызова не будет, то компилятор попробует вызвать констуктор по умолчанию. В случае отсутствия констуктора по умолчанию возникнет ошибка (в чем ты уже убедился)

ЗЫ
констуктор по умолчанию — это констркутор без параметров, или с параметрами, имеющими значения по умолчанию.

.
void main()
CB bl;
>

SVV>В результате ошибка компиллятора: error C2512: 'CA' : no appropriate default constructor available
SVV>Ошибка пропадает, если использовать конструкторы без параметров (или только СА без параметров).
SVV>Как правильно переопределить конструкторы с параметрами?

Когда ты создаешь объект у которого есть базовые классы — то сначала вызываются конструкторы для базовых классов, а потом конструктор для самого объекта.
То что ты вызываешь конструктор для СА внутри CB ничего не значит для компилятора.
И вообще — это ты просто создал временный объект CA, который будет уничтожен после выхода из конструктора.
Компилятор сам пытается вызвать конструктор по умолчанию для СА. А такого просто нет — вот он и ругается.
Нужно писать вот так:

Этим ты говоришь, что перед выполнением конструктора CB нужно выполнить конструктор CA.

Здравствуйте, SVV, Вы писали:

SVV>Спасибо.
SVV>Компиллятор уже поборол. Сейчас буду выяснять правильно ли это работает.
Борьба с компилятором до добра не доведет
С компилятором надо по-хорошему.


В результате ошибка компиллятора: error C2512: 'CA' : no appropriate default constructor available
Ошибка пропадает, если использовать конструкторы без параметров (или только СА без параметров). Как правильно переопределить конструкторы с параметрами?

Спасибо.
Компиллятор уже поборол. Сейчас буду выяснять правильно ли это работает.

Здравствуйте, Bell, Вы писали:

B>Борьба с компилятором до добра не доведет
Согласен.
B>С компилятором надо по-хорошему.
А двоеточие означает что конструктор СВ наследует код CA, или всего лишь определяет какой базовый конструктор вызывать, если явного вызова не будет?

Репутация: нет
Всего: нет

Есть задача реализации наследования шаблонов класса, например:

Код

template class A
public:
A();
~A();

template class B : public A
public:
B(int i);
~B();

Ошибка следующего содержания:
Ошибка 4 error C2512: A: нет подходящего конструктора по умолчанию

Смущает то, что ошибка ссылается на класс A (он родитель), но если бы конструкторы у обоих классов были одинаковые все было бы отлично.

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

Репутация: 81
Всего: 211

Цитата(shtuceron @ 24.2.2011, 16:20 )
Ошибка следующего содержания:
Ошибка 4 error C2512: A: нет подходящего конструктора по умолчанию

Не верю ©
Покажи реальный код, который компилируешь. Этот ошибку вызывать не может.

Репутация: 144
Всего: 250

приведенный пример не компилируем из за отсутствия ; после описания класса..

Репутация: нет
Всего: нет

Извиняюсь и впрямь ошибка, но сути дела не меняет!

а вот и исходники программы (проект VS2008): файлы

using namespace System;

Репутация: 144
Всего: 250

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

Репутация: нет
Всего: нет

Цитата(mes @ 24.2.2011, 17:46)
в классе А, нет конструктора по-умолчанию, поэтому при наследовании от него, Вы должны его инициализировать в списке инициализации наследника..

Репутация: 81
Всего: 211

Цитата(shtuceron @ 24.2.2011, 17:53 )
Я извиняюсь но как??

Репутация: нет
Всего: нет

а точно так? просто в классе В нет конструктора с такими параметрами да и переменная i в конструкторе класса передается нетипизированной.

пробовал запихнуть таким образом (если правильно Вас понял), но ошибки так и прут.

Репутация: 81
Всего: 211

Репутация: 144
Всего: 250

в зависимости от того чего пытаетесь добиться..

Репутация: нет
Всего: нет

Огромная Вам благодарность, все заработало, теперь напоследок хочется уяснить одну вещь, почему нельзя определить конструктор дочернего класса не обращая внимания на конструктор родитель? Из каких соображений это сделано?

Репутация: 81
Всего: 211

Цитата(shtuceron @ 24.2.2011, 18:32 )
почему нельзя определить конструктор дочернего класса не обращая внимания на конструктор родитель? Из каких соображений это сделано?


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

Репутация: 6
Всего: 10

Цитата(shtuceron @ 24.2.2011, 18:32 )
Огромная Вам благодарность, все заработало, теперь напоследок хочется уяснить одну вещь, почему нельзя определить конструктор дочернего класса не обращая внимания на конструктор родитель?


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

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это! хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn


0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »

[ Время генерации скрипта: 0.1735 ] [ Использовано запросов: 21 ] [ GZIP включён ]

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