Есть базовый класс:
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
I checked out a post similar to this but the linkage was different the issue was never resolved. The problem with mine is that for some reason the linker is expecting there to be a definition for the base class, but the base class is just a interface. Below is the error in it’s entirety
c:usersnumerical25desktopintro todirectxgodfilesgxrendermanagergxrendermanagergxrendermanagergxdx.h(2) : error C2504: 'GXRenderer' : base class undefined
Below is the code that shows how the headers link with one another
GXRenderManager.h
#ifndef GXRM
#define GXRM
#include <windows.h>
#include "GXRenderer.h"
#include "GXDX.h"
#include "GXGL.h"
enum GXDEVICE {
DIRECTX,
OPENGL
};
class GXRenderManager {
public:
static int Ignite(GXDEVICE);
private:
static GXRenderer *renderDevice;
};
#endif
at the top of GxRenderManager, there is GXRenderer , windows, GXDX, GXGL headers. I am assuming by including them all in this document. they all link to one another as if they were all in the same document. correct me if I am wrong cause that’s how a view headers. Moving on…
GXRenderer.h
class GXRenderer {
public:
virtual void Render() = 0;
virtual void StartUp() = 0;
};
GXGL.h
class GXGL: public GXRenderer {
public:
void Render();
void StartUp();
};
GXDX.h
class GXDX: public GXRenderer {
public:
void Render();
void StartUp();
};
GXGL.cpp and GXDX.cpp respectively
#include "GXGL.h"
void GXGL::Render()
{
}
void GXGL::StartUp()
{
}
//...Next document
#include "GXDX.h"
void GXDX::Render()
{
}
void GXDX::StartUp()
{
}
Not sure whats going on. I think its how I am linking the documents, I am not sure.
iandi 1 / 1 / 0 Регистрация: 21.11.2010 Сообщений: 20 |
||||||||||||
1 |
||||||||||||
Не определен базовый класс09.09.2012, 01:13. Показов 16713. Ответов 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 2155 / 1664 / 702 Регистрация: 27.07.2012 Сообщений: 4,949 |
||||
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 |
2155 / 1664 / 702 Регистрация: 27.07.2012 Сообщений: 4,949 |
|
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 |
2155 / 1664 / 702 Регистрация: 27.07.2012 Сообщений: 4,949 |
|
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 |
2155 / 1664 / 702 Регистрация: 27.07.2012 Сообщений: 4,949 |
|
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 — 16.06.17, 07:12 |
JoeUser |
|
Опубликуй весь код нормально, ибо приходится только гадать. |
KILLER |
|
Цитата agapUP @ 16.06.17, 08:33 Вот че это за … такая? А с чего ты вдруг решил что оно по другому должно работать? Вот ты написал:
child.h child pragma once class Cchild: public Cbase { //… };
Расскажи пожалуйста, откуда компилятор, при компиляции этого кода будет знать что такое CBase и где он объявлен? Добавлено 16.06.17, 08:58 Цитата agapUP @ 16.06.17, 07:10 Все работало!!!!!! Очень странно что оно все работало. Не должно было работать, должно было выдать вот такую ошибку, которую ты сейчас и получил. Сообщение отредактировано: KILLER — 16.06.17, 08:58 |
agapUP |
|
Цитата KILLER @ 16.06.17, 08:57 Ты не пробовал #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 @ 16.06.17, 10:33 И тут возникает вопрос: а что мне скажет компилятор на многократное подключение «base.h»? Ничего не скажет, pragma once для этого и нужен, чтобы включал только один раз Сообщение отредактировано: Kray74 — 16.06.17, 10:36 |
KILLER |
|
Цитата agapUP @ 16.06.17, 10:33 Разве я этого не писал?… Это ты написал в cpp файле, после отработки препроцессора, у тебя в твой cpp файл, включится *.h файл и будет все выглядеть вот так вот:
// child.tmp — это выходной файл, который сгенерируется после того, как отработает препроцессор class Cchild: public Cbase { //… }; class Cbase { //… }; … //! Реализация Cchild И выходит, что в точке, где ты объявляешь свой класс Cchild — компилятор ничего не знает про тот класс, от которого ты наследуешься(в твоем случае про класс Cbase), он узнает о том, где он объявлен и что это за класс уже ниже. А до этого он про него не знает, вот он тебе и говорит — я не знаю что за такой класс, от которого ты наследуешься. Сообщение отредактировано: KILLER — 16.06.17, 12:15 |
agapUP |
|
Спасибо Не думал, что препроцессор так переворачивает подключения
*.cpp //все включения #include <> … e.g.:#include «base.h» … e.g.:#include «child.h» Cchild::Cchild() {} //И т.д. //… Не жалую я подключения хидеров в *.h-файлы! |
Kray74 |
|
Цитата agapUP @ 19.06.17, 12:24 Не жалую я подключения хидеров в *.h-файлы! Ну почему же? Если в *.h файле есть зависимость, то пусть он хэдер с этой зависимостью и подключает. |
KILLER |
|
Цитата agapUP @ 19.06.17, 12:24 Не думал, что препроцессор так переворачивает подключения Ничего он не переворачивает, в С/С++ единица компиляции считается с/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 — 19.06.17, 13:53 |
JoeUser |
|
Цитата KILLER @ 19.06.17, 13:52 #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 @ 19.06.17, 13:36 Ну почему же? Если в *.h файле есть зависимость, то пусть он хэдер с этой зависимостью и подключает. Знаете… Для меня это как-то не убедительно звучит! Вот пример, стандартные библиотеки, типа #include <string> — у меня и в мыслях нет их в хедер загонять!!!!! Даже и не экспериментировал! Когда использовал «ifndef …» — компелятор ругался о многократном включении. Вот и сформировалось у меня такое представление. А зависимость показана в реализации: файл ipo1.cpp Сообщение отредактировано: agapUP — 20.06.17, 10:46 |
_lcf_ |
|
Цитата agapUP @ 20.06.17, 10:42 Вот пример, стандартные библиотеки, типа #include <string> — у меня и в мыслях нет их в хедер загонять!!!! а это потому что ты не наследуешься от них. зафорвардить можно только классы, да и то только если будешь использовать указатели — так как они занимают фиксированный объём. ну еще енумы всякие. а если ты хочешь в хидере обьявить сам объект или наследоваться, то тогда надо делать инклюд, иначе компиль не знает сколько места надо выделить под эти объекты. Сообщение отредактировано: _lcf_ — 20.06.17, 10:57 |
KILLER |
|
Цитата agapUP @ 20.06.17, 10:42 НО!! Чем мой пример отличается от концепции С++?! В каком смысле? По концепции С++, ты написал неработающий код. Смотри? давай на пальцах, вот что ты написал:
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 @ 20.06.17, 10:42 Ведь поля класса типа string определяются в описании самого класса, хотя включение этой библиотеки Чего? Если ты не подключишь string в хидер, но будешь его там использовать — будет ровно такая же ошибка. Цитата agapUP @ 20.06.17, 10:42 Когда использовал «ifndef …» — компелятор ругался о многократном включении. Вот и сформировалось у меня такое представление. А зависимость показана в реализации: файл ipo1.cpp компилятор может ругатся о многократном включении, если отсуствуют гарды компиляции:
#ifndef __SOME_HEADER_FILE__ //! гард предотвращающий повторное включение хидера. #define __SOME_HEADER_FILE__ //! Какие то объявления #endif |
Cfon |
|
agapUP |
agapUP |
|
Доброе время суток Цитата _lcf_ @ 20.06.17, 10:56 …иначе компиль не знает сколько места надо выделить под эти объекты. Я не берусь судить, ибо не знаю! , но после этих строк мне чет зачесалось в пятой точке , что мои траблы связаны с выделением-затиранием память процесса ВОТ! Один проект! Два дочерних и один базовый: … А скрины вставить не вышло….. Но там суть такая: для класса А я хидер базового включил в срр-файл класса А — и ошибки «С2504 — не определен базовый класс» не возникло! Добавлено 23.06.17, 07:49 Сообщение отредактировано: agapUP — 23.06.17, 07:49 |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- C/C++: Общие вопросы
- Следующая тема
[ Script execution time: 0,0500 ] [ 16 queries used ] [ Generated: 7.06.23, 09:12 GMT ]
После этого урока (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
Другие решения
Других решений пока нет …