Есть базовый класс:
class csymbol
{
public:
enum_symbol_type type;
enum_keywords kw;
enum_operations op;
string ident;
cvalue value;
};
От него наследуется класс
class cvalue : public csymbol
{
public:
const_types type;
int cint;
double creal;
char cchar;
string cstring;
bool cbool;
};
При сборке получаю ошибку Ошибка C2504 csymbol: не определен базовый класс
. Что я делаю не так?
задан 2 мар 2018 в 18:47
3
Конфигурация классов бессмысленна. Класс csymbol
включает класс cvalue
в качестве подобъекта, а класс cvalue
включает класс csymbol
в качестве подобъекта. Это невозможно, ибо представляет собой бесконечно рекурсивную структуру данных.
Угадываю, что вы устроили у себя в коде циклическое включение заголовочных файлов и, ожидаемо, получили эту ошибку.
Не пытайтесь создавать структуры данных с циклическим включением подобъектов — это невозможно. И не пытайтесь делать циклическое включение заголовочных файлов — это ничего не даст.
ответ дан 2 мар 2018 в 19:52
Добавьте перед классами предварительные объявления:
class csymbol;
class cvalue;
Попробуйте вместо
cvalue value;
использовать
cvalue *value;
Вот этот код у меня скомпилировался:
#include "stdafx.h"
#include <string>
using namespace std;
#define const_types int
enum enum_symbol_type{a,b};
enum enum_keywords{c,d};
enum enum_operations{e,f};
class csymbol;
class cvalue;
class csymbol
{
public:
enum_symbol_type type;
enum_keywords kw;
enum_operations op;
string ident;
cvalue* value;
};
class cvalue : public csymbol
{
public:
const_types type;
int cint;
double creal;
char cchar;
string cstring;
bool cbool;
};
int _tmain(int argc, _TCHAR* argv[])
{
cvalue value;
csymbol symbol;
return 0;
}
ответ дан 2 мар 2018 в 19:22
MindCleanerMindCleaner
8041 золотой знак5 серебряных знаков11 бронзовых знаков
2
iandi 1 / 1 / 0 Регистрация: 21.11.2010 Сообщений: 20 |
||||||||||||
1 |
||||||||||||
Не определен базовый класс09.09.2012, 01:13. Показов 16970. Ответов 19 Метки нет (Все метки)
Доброго времени суток. Столкнулся с проблемой при наследовании, и не могу разобраться, как решить. Хедеры
При компиляции выдает ошибку: 1> Tug.cpp В чем тут проблема? Компилятор VS10
0 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
09.09.2012, 01:13 |
Ответы с готовыми решениями: Не определен базовый класс #pragma once #include "device.h" class… Не определен базовый класс C_Button: Не определен базовый класс Не определен базовый класс 19 |
574 / 557 / 47 Регистрация: 16.12.2011 Сообщений: 1,389 |
|
09.09.2012, 01:17 |
2 |
class SPoint abstract а если убрать слово abstract, то ошибки остаются?
0 |
1 / 1 / 0 Регистрация: 21.11.2010 Сообщений: 20 |
|
09.09.2012, 01:18 [ТС] |
3 |
class SPoint abstract а если убрать слово abstract, то ошибки остаются? Все равно остаются.
0 |
John Prick 2207 / 1706 / 721 Регистрация: 27.07.2012 Сообщений: 5,091 |
||||
09.09.2012, 01:19 |
4 |
|||
Не на слово abstract ли ругается? Откуда и зачем оно тут? Добавлено через 31 секунду Все равно остаются. Какие именно? Те же?
0 |
1 / 1 / 0 Регистрация: 21.11.2010 Сообщений: 20 |
|
09.09.2012, 01:24 [ТС] |
5 |
Не на слово abstract ли ругается? Откуда и зачем оно тут? Для того, чтобы нельзя было создать экземпляры класса. Такие же.
0 |
574 / 557 / 47 Регистрация: 16.12.2011 Сообщений: 1,389 |
|
09.09.2012, 01:31 |
6 |
Реализация у базового класса есть? покажите срр файл
0 |
2207 / 1706 / 721 Регистрация: 27.07.2012 Сообщений: 5,091 |
|
09.09.2012, 01:33 |
7 |
Для того, чтобы нельзя было создать экземпляры класса. Это понятно. Но это слово не из стандарта. Кидайте весь проект, иначе ничего не понятно.
0 |
iandi 1 / 1 / 0 Регистрация: 21.11.2010 Сообщений: 20 |
||||
09.09.2012, 01:35 [ТС] |
8 |
|||
Реализация у базового класса есть? покажите срр файл Есть.
0 |
574 / 557 / 47 Регистрация: 16.12.2011 Сообщений: 1,389 |
|
09.09.2012, 01:35 |
9 |
Это понятно. Но это слово не из стандарта. Кидайте весь проект, иначе ничего не понятно. Весь лучше не надо — там еще танкер и порт есть)
0 |
1180 / 893 / 94 Регистрация: 03.08.2011 Сообщений: 2,461 |
|
09.09.2012, 01:37 |
10 |
class SPoint abstract Бред, уберите слово abstract. Абстрактный класс, это класс который содержит хотя бы одну чисто виртуальную функцию, у Вас она есть:
virtual void run() = 0;
0 |
2207 / 1706 / 721 Регистрация: 27.07.2012 Сообщений: 5,091 |
|
09.09.2012, 01:42 |
11 |
Весь лучше не надо — там еще танкер и порт есть) НЕ поверите — пытаюсь повторить вашу ошибку у себя. Без танкера, порта, а самое главное int main(void) ничего у меня не получится.
0 |
574 / 557 / 47 Регистрация: 16.12.2011 Сообщений: 1,389 |
|
09.09.2012, 01:53 |
12 |
НЕ поверите — пытаюсь повторить вашу ошибку у себя. Без танкера, порта, а самое главное int main(void) ничего у меня не получится. Ошибка-то не моя, но я тоже не могу ее воспроизвести в liveworkspace. Надо бы в студии пробовать, но нет возможности
0 |
iandi 1 / 1 / 0 Регистрация: 21.11.2010 Сообщений: 20 |
||||||||
09.09.2012, 01:57 [ТС] |
13 |
|||||||
Это понятно. Но это слово не из стандарта. Кидайте весь проект, иначе ничего не понятно. Весь проект еще не готов. Просто по мере реализации отдельных классов — компилю, чтобы ошибки найти. Вот реализация производных классов: Кликните здесь для просмотра всего текста
0 |
novi4ok 556 / 510 / 25 Регистрация: 23.07.2009 Сообщений: 2,359 Записей в блоге: 1 |
||||||||||||
09.09.2012, 01:59 |
14 |
|||||||||||
[SPOILER=Хедеры][CPP] class Tanker; а что это такое? зачем эти инклуды? ты сам себя за волосы пытался поднять? и здесь тоже не получится.
и ClassB.h:
компилятор открывает первый файл, встречает инклуд и включает его содержимое. там — инклуд, призывающий включить первый файл. идет распознавать ClassA, но не знает, что такое ClassB. если идет с другой стороны — та же история. для этого и существует «объявление наперед»:
и компилятор все понимает. он знает, что ClassB — это класс, подробности о котором он узнает позже.
1 |
574 / 557 / 47 Регистрация: 16.12.2011 Сообщений: 1,389 |
|
09.09.2012, 02:05 |
15 |
novi4ok, там же вроде бы не ясно, есть ли перекрестные ссылки или нет. Как вы это поняли?
0 |
1 / 1 / 0 Регистрация: 21.11.2010 Сообщений: 20 |
|
09.09.2012, 02:11 [ТС] |
16 |
а что это такое? зачем эти инклуды? При удалении инклудов, появляется ошибка «использование неопределенного типа». Да и #pragma once, насколько я понимаю, следит за тем, чтобы хедер подключался один раз?
0 |
I.M. 574 / 557 / 47 Регистрация: 16.12.2011 Сообщений: 1,389 |
||||
09.09.2012, 02:49 |
17 |
|||
А ведь novi4ok был скорее всего прав — полистал другие форумы — у людей аналогичная ошибка вылезала при некорректном include. Надо поискать все файлы, которые подключают заголовочные файлы наследников. В вашем случае, надо искать те файлы, которые инклудят в себя terminal.h или tug.h. Скорее всего один из таких файлов косвенно или напрямую инклудится в базовый класс. Также с помощью
1 |
2207 / 1706 / 721 Регистрация: 27.07.2012 Сообщений: 5,091 |
|
09.09.2012, 02:57 |
18 |
Без всех файлов проекта (ну или хотя бы тех, что тут в коде не к ночи были упомянуты) ничего не собрать и не понять. Ясно одно — что-то где-то не определено.
1 |
1 / 1 / 0 Регистрация: 21.11.2010 Сообщений: 20 |
|
09.09.2012, 04:29 [ТС] |
19 |
Спасибо, разобрался. Все-таки из-за перекрестных инклудов была ошибка. А где можно подробнее почитать о предварительном объявлении? Ну и проектировании, чтобы в будущем этого избежать. В Буче как-то на этот счет ничего не нашел…
0 |
87 / 87 / 1 Регистрация: 19.06.2012 Сообщений: 245 |
|
09.09.2012, 10:22 |
20 |
Я думаю у тебя #pragma once не работал. Юзай include guard — так портабельнее и стандартнее
0 |
|
|
|
Ошибка С2504 — не определен базовый класс
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
Доброе время суток Суть вот в чем: base.h base pragma once class Cbase { //… }; base.cpp base //реализация base child.h child pragma once class Cchild: public Cbase { //… }; child.cpp #include «base.h» #include «child.h» //Реализация Cchild Все работало!!!!!! Сообщение отредактировано: agapUP — |
JoeUser |
|
Опубликуй весь код нормально, ибо приходится только гадать. |
KILLER |
|
Цитата agapUP @ Вот че это за … такая? А с чего ты вдруг решил что оно по другому должно работать? Вот ты написал: child.h child pragma once class Cchild: public Cbase { //… };
Расскажи пожалуйста, откуда компилятор, при компиляции этого кода будет знать что такое CBase и где он объявлен? Добавлено Цитата agapUP @ Все работало!!!!!! Очень странно что оно все работало. Не должно было работать, должно было выдать вот такую ошибку, которую ты сейчас и получил. Сообщение отредактировано: KILLER — |
agapUP |
|
Цитата KILLER @ Ты не пробовал #include «base.h» подключить в *.h файл? Подключил — работает! НО! Разве я этого не писал?… … child.cpp #include «base.h» #include «child.h» Тут какая логика, этот «Cbase» — общие алгоритмы: нутация, расчет векторов и т.д… #include «child1.h» #include «child2.h» #include «child3.h» //… void main() { //Задача 2 child2.task() //Анализ данных //… //Задача 1 child1.task() //Анализ данных //… //Задача 1 child3.task() //Анализ данных //… }
И тут возникает вопрос: а что мне скажет компилятор на многократное подключение «base.h»? |
Kray74 |
|
Цитата agapUP @ И тут возникает вопрос: а что мне скажет компилятор на многократное подключение «base.h»? Ничего не скажет, pragma once для этого и нужен, чтобы включал только один раз Сообщение отредактировано: Kray74 — |
KILLER |
|
Цитата agapUP @ Разве я этого не писал?… Это ты написал в cpp файле, после отработки препроцессора, у тебя в твой cpp файл, включится *.h файл и будет все выглядеть вот так вот: // child.tmp — это выходной файл, который сгенерируется после того, как отработает препроцессор class Cchild: public Cbase { //… }; class Cbase { //… }; … //! Реализация Cchild И выходит, что в точке, где ты объявляешь свой класс Cchild — компилятор ничего не знает про тот класс, от которого ты наследуешься(в твоем случае про класс Cbase), он узнает о том, где он объявлен и что это за класс уже ниже. А до этого он про него не знает, вот он тебе и говорит — я не знаю что за такой класс, от которого ты наследуешься. Сообщение отредактировано: KILLER — |
agapUP |
|
Спасибо Не думал, что препроцессор так переворачивает подключения *.cpp //все включения #include <> … e.g.:#include «base.h» … e.g.:#include «child.h» Cchild::Cchild() {} //И т.д. //… Не жалую я подключения хидеров в *.h-файлы! |
Kray74 |
|
Цитата agapUP @ Не жалую я подключения хидеров в *.h-файлы! Ну почему же? Если в *.h файле есть зависимость, то пусть он хэдер с этой зависимостью и подключает. |
KILLER |
|
Цитата agapUP @ Не думал, что препроцессор так переворачивает подключения Ничего он не переворачивает, в С/С++ единица компиляции считается с/cpp файл. #include — макрос вот ты пишешь: //! File: A.h #ifndef _A_H_ #define _A_H_ class A { … }; #endif //! File: A.cpp #include «A.h» //! реализация A::A() { … } …
В итоге у тебя есть 1 класс, который разнесен на два файла, как только ты запустишь компиляцию, препроцессор вместо строчки #include «A.h» подставит содержимое этого файла(к слову так даже массивы можно объявлять.) //! File: A.h #ifndef _A_H_ #define _A_H_ class A : public CBase { … }; #endif Что такое CBase ? Верно ты не знаешь, а с какого перепуга компилятор должен об этом узнать? Другое дело, что есть инструменты сказать компилятору о том, чтоб он особо не ругался, т.к. какой нибудь класс уже где то объявлен, например это касается forward declarations, но допустимы если у тебя ссылочный тип данных или указатель. А тут наследование, соответственно, чтобы компилятор знал что это за тип, ему его нужно объявить, а у тебя идет использование типа до того, как ты его объявил. Сообщение отредактировано: KILLER — |
JoeUser |
|
Цитата KILLER @ #include — макрос Если точнее — директива препроцессора. |
agapUP |
|
Доброе время суток НО!! Чем мой пример отличается от концепции С++?! //ipo1.h clas Cipo: public CCommAlg { //… }; //… //Конец ipo1.h //ipo1.cpp #include <vector> //… #include <string> #include <hrono> //… #include «CommAlg.h» !!!!!!!!!!!!!!!!!!!!!!!!!! //… #include «ipo1.h» !!!!!!!!!!!!!!!!!!!!!!!!!!!!! /* РЕАЛИЗАЦИЯ МЕТОДОВ Cipo1 */ //Конец ipo1.cpp Так вот чем может (по концепции) реализация в ipo1.cpp: //… #include «CommAlg.h» //… #include «ipo1.h» //… Может отличаться от: #pragma once #include «CommAlg.h» class Cipo: public CCommAlg
? Использую компилятор VS2012 Цитата Kray74 @ Ну почему же? Если в *.h файле есть зависимость, то пусть он хэдер с этой зависимостью и подключает. Знаете… Для меня это как-то не убедительно звучит! Вот пример, стандартные библиотеки, типа #include <string> — у меня и в мыслях нет их в хедер загонять!!!!! Даже и не экспериментировал! Когда использовал «ifndef …» — компелятор ругался о многократном включении. Вот и сформировалось у меня такое представление. А зависимость показана в реализации: файл ipo1.cpp Сообщение отредактировано: agapUP — |
_lcf_ |
|
Цитата agapUP @ Вот пример, стандартные библиотеки, типа #include <string> — у меня и в мыслях нет их в хедер загонять!!!! а это потому что ты не наследуешься от них. зафорвардить можно только классы, да и то только если будешь использовать указатели — так как они занимают фиксированный объём. ну еще енумы всякие. а если ты хочешь в хидере обьявить сам объект или наследоваться, то тогда надо делать инклюд, иначе компиль не знает сколько места надо выделить под эти объекты. Сообщение отредактировано: _lcf_ — |
KILLER |
|
Цитата agapUP @ НО!! Чем мой пример отличается от концепции С++?! В каком смысле? По концепции С++, ты написал неработающий код. Смотри? давай на пальцах, вот что ты написал: int main() { int x = 10; int result = x + y; int y = 20; std::cout << «x+y=» << result; return 0; }
Компилятор тебе говорит — «Я не знаю что за такая переменная y в выражении int result = x + y;» Цитата agapUP @ Ведь поля класса типа string определяются в описании самого класса, хотя включение этой библиотеки Чего? Если ты не подключишь string в хидер, но будешь его там использовать — будет ровно такая же ошибка. Цитата agapUP @ Когда использовал «ifndef …» — компелятор ругался о многократном включении. Вот и сформировалось у меня такое представление. А зависимость показана в реализации: файл ipo1.cpp компилятор может ругатся о многократном включении, если отсуствуют гарды компиляции: #ifndef __SOME_HEADER_FILE__ //! гард предотвращающий повторное включение хидера. #define __SOME_HEADER_FILE__ //! Какие то объявления #endif |
Cfon |
|
agapUP |
agapUP |
|
Доброе время суток Цитата _lcf_ @ …иначе компиль не знает сколько места надо выделить под эти объекты.
Я не берусь судить, ибо не знаю! ВОТ! Один проект! Два дочерних и один базовый: … А скрины вставить не вышло….. Но там суть такая: для класса А я хидер базового включил в срр-файл класса А — и ошибки «С2504 — не определен базовый класс» не возникло! Добавлено Сообщение отредактировано: agapUP — |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- C/C++: Общие вопросы
- Следующая тема
[ Script execution time: 0,0586 ] [ 16 queries used ] [ Generated: 22.09.23, 15:52 GMT ]
Ошибка: «Не определен базовый класс»
В программировании, особенно в объектно-ориентированном программировании, ошибки могут быть неизбежными. Одна из таких ошибок, с которой вы, возможно, столкнулись, — это ошибка «Не определен базовый класс». В этой статье мы рассмотрим причины возникновения этой ошибки и предложим решения для ее исправления.
Первоначально, давайте разберемся, что такое базовый класс. В объектно-ориентированном программировании классы могут наследовать свойства и методы других классов. Класс, от которого наследуются другие классы, называется базовым классом или родительским классом. Класс, который наследует свойства и методы от базового класса, называется производным классом или дочерним классом.
Ошибка «Не определен базовый класс» обычно возникает, когда производный класс пытается наследовать свойства и методы от несуществующего базового класса. Это может произойти по ряду причин.
1. Отсутствие или неправильное указание имени базового класса. Возможно, вы случайно написали неправильное имя базового класса при объявлении производного класса. Проверьте свой код и убедитесь, что вы правильно указали имя базового класса.
Например, предположим, у вас есть базовый класс «Person» и вы хотите создать производный класс «Student», который наследует свойства и методы от базового класса. Ошибка «Не определен базовый класс» может возникнуть, если вы напишете «class Student: Student» вместо «class Student: Person».
2. Отсутствие подключения файла с определением базового класса. Если базовый класс определен в отдельном файле, убедитесь, что вы правильно подключили этот файл в вашем коде. Если файл не подключен или его путь указан неправильно, компилятор не сможет найти определение базового класса, что приведет к ошибке.
3. Повторное определение базового класса. Возможно, вы дважды определили базовый класс в одном файле или в разных файлах, подключенных к проекту. При этом компилятор не сможет определить, какой из определений использовать, и выдаст ошибку «Не определен базовый класс».
Чтобы исправить ошибку «Не определен базовый класс», вам необходимо выполнить следующие шаги:
1. Проверьте правильность написания имени базового класса в определении производного класса. Убедитесь, что вы правильно указали имя базового класса и что оно соответствует имени базового класса, от которого вы хотите наследовать свойства и методы.
2. Проверьте подключение файла с определением базового класса. Убедитесь, что вы правильно подключили файл с определением базового класса и указали правильный путь к этому файлу.
3. Проверьте наличие повторного определения базового класса. Убедитесь, что базовый класс определен только один раз в вашем проекте и не повторяется в разных файлах.
4. Проверьте корректность наследования классов. Если базовый класс является абстрактным классом или интерфейсом, убедитесь, что производный класс правильно наследует свойства и методы от базового класса.
5. Перекомпилируйте свой проект после внесенных изменений. После исправления ошибок сохраните свой код и перекомпилируйте проект, чтобы убедиться, что ошибка «Не определен базовый класс» исчезла.
В заключение можно сказать, что ошибка «Не определен базовый класс» свидетельствует о том, что компилятор не может найти определение базового класса, от которого производный класс пытается наследовать свойства и методы. Эта ошибка может возникнуть из-за неправильного указания имени базового класса, неправильного подключения файла с определением базового класса или повторного определения базового класса. Чтобы исправить эту ошибку, проверьте правильность имени базового класса, правильность подключения файла с определением базового класса и отсутствие повторного определения базового класса. После выполнения этих шагов перекомпилируйте свой проект и убедитесь, что ошибка больше не возникает.
После этого урока (https://www.youtube.com/watch?v=gq2Igdc-OSI&Индекс = 52&список = PLAE85DE8440AA6B83) Я столкнулся с 4 ошибками в Visual Studio C ++ 2017. 3 из них — это одно и то же, и просто повторяется «Мать»: базовый класс не определен в файле daughter.h. Другая ошибка гласит: «sayName» не является членом «Daughter». Теперь вот код. Это довольно просто, что я хочу, чтобы программа печатала … Я хочу, чтобы она напечатала две строки «Что ты там делаешь?» Если бы вы могли помочь мне с этим ответом, это было бы здорово. Спасибо.
Для основного файла
`#include» stdafx.h «#include
#include «Daughter.h» #include «Mother.h» с использованием пространства имен std;
int main()
{
Mother pot;
pot.sayName();
Daughter kettle;
kettle.sayName();
int pause = 0;
cin >> pause;
}
Mother.h
#ifndef MOTHER_H
#define MOTHER_H
class Mother
{
public:
Mother();
void sayName();
};
#endif
Mother.cpp
#include "stdafx.h"#include<iostream>
#include"Daughter.h"#include"Mother.h"using namespace std;
Mother::Mother()
{
}
void Mother::sayName() {
cout << "What are you doing there?" << endl;
}
Daughter.h
#ifndef DAUGHTER_H
#define DAUGHTER_H
class Daughter:public Mother
{
public:
Daughter();
};
#endif
Daughter.cpp
#include "stdafx.h"#include<iostream>
#include"Daughter.h"#include"Mother.h"using namespace std;
Daughter::Daughter()
{
}
2
Решение
Когда класс наследует другой, он должен включать заголовок родительского класса в свой заголовок. В вашем случае вы должны добавить #include "Mother.h"
в верхней части дочернего заголовка (не только в файле .cpp). Другая ошибка происходит из-за первой, и исправление должно решить ее.
Когда вы пишете синтаксис наследования class Daughter : public Mother
определение класса Daughter должно иметь доступ к информации о родительском классе по нескольким причинам. Одним из них является информация о унаследованных методах, которая стала причиной вашей второй ошибки.
1
Другие решения
Других решений пока нет …