Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.81.184.170] |
|
Сообщ.
#1
,
|
|
|
Доброе время суток
ПОМОГИТЕЕЕЕЕЕ!!!!Пожалуйста Суть вот в чем: 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 Все работало!!!!!! Добавляю так же Cchild2 - И ОШИБКА!!!! Удалил из проекта файлы Cchild2!!! Все равно эта ошибка Вот че это за ... такая? |
Сообщ.
#2
,
|
|
|
Опубликуй весь код нормально, ибо приходится только гадать.
А если "убираешь" модули (классы) - пересобирай проект полностью, с удалением старых объектных модулей. |
Сообщ.
#3
,
|
|
|
Цитата agapUP @ Вот че это за ... такая? А с чего ты вдруг решил что оно по другому должно работать? Вот ты написал: child.h child pragma once class Cchild: public Cbase { //... }; Расскажи пожалуйста, откуда компилятор, при компиляции этого кода будет знать что такое CBase и где он объявлен? Ты не пробовал #include "base.h" подключить в *.h файл? Добавлено Цитата agapUP @ Все работало!!!!!! Очень странно что оно все работало. Не должно было работать, должно было выдать вот такую ошибку, которую ты сейчас и получил. |
Сообщ.
#4
,
|
|
|
Цитата KILLER @ Ты не пробовал #include "base.h" подключить в *.h файл? Подключил - работает! НО! Разве я этого не писал?... ... child.cpp #include "base.h" #include "child.h" Тут какая логика, этот "Cbase" - общие алгоритмы: нутация, расчет векторов и т.д... Его поля и методы используются, скажем, в Child1,Child2,Child3.... Теперь обобщенная логика main(): #include "child1.h" #include "child2.h" #include "child3.h" //... void main() { //Задача 2 child2.task() //Анализ данных //... //Задача 1 child1.task() //Анализ данных //... //Задача 1 child3.task() //Анализ данных //... } И тут возникает вопрос: а что мне скажет компилятор на многократное подключение "base.h"? |
Сообщ.
#5
,
|
|
|
Цитата agapUP @ И тут возникает вопрос: а что мне скажет компилятор на многократное подключение "base.h"? Ничего не скажет, pragma once для этого и нужен, чтобы включал только один раз |
Сообщ.
#6
,
|
|
|
Цитата agapUP @ Разве я этого не писал?... Это ты написал в cpp файле, после отработки препроцессора, у тебя в твой cpp файл, включится *.h файл и будет все выглядеть вот так вот: // child.tmp - это выходной файл, который сгенерируется после того, как отработает препроцессор class Cchild: public Cbase { //... }; class Cbase { //... }; ... //! Реализация Cchild И выходит, что в точке, где ты объявляешь свой класс Cchild - компилятор ничего не знает про тот класс, от которого ты наследуешься(в твоем случае про класс Cbase), он узнает о том, где он объявлен и что это за класс уже ниже. А до этого он про него не знает, вот он тебе и говорит - я не знаю что за такой класс, от которого ты наследуешься. |
Сообщ.
#7
,
|
|
|
Спасибо
Не думал, что препроцессор так переворачивает подключения Всегда так подключал *.cpp //все включения #include <> ... e.g.:#include "base.h" ... e.g.:#include "child.h" Cchild::Cchild() {} //И т.д. //... Не жалую я подключения хидеров в *.h-файлы! |
Сообщ.
#8
,
|
|
|
Цитата agapUP @ Не жалую я подключения хидеров в *.h-файлы! Ну почему же? Если в *.h файле есть зависимость, то пусть он хэдер с этой зависимостью и подключает. |
Сообщ.
#9
,
|
|
|
Цитата 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, но допустимы если у тебя ссылочный тип данных или указатель. А тут наследование, соответственно, чтобы компилятор знал что это за тип, ему его нужно объявить, а у тебя идет использование типа до того, как ты его объявил. |
Сообщ.
#10
,
|
|
|
Скрытый текст Цитата KILLER @ #include - макрос Если точнее - директива препроцессора. |
Сообщ.
#11
,
|
|
|
Доброе время суток
Спасибо, что уделяете мне время KILLER, спасибо за разъяснения НО!! Чем мой пример отличается от концепции С++?! Прошу у Вас прощения , видать я не очень наглядно продемонстрировал вопрос... Попытаюсь исправить: //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 ? Ведь поля класса типа string определяются в описании самого класса, хотя включение этой библиотеки осуществляется в ipo1.cpp!!! Использую компилятор VS2012 Цитата Kray74 @ Знаете... Для меня это как-то не убедительно звучит! Вот пример, стандартные библиотеки, типа #include <string> - у меня и в мыслях нет их в хедер загонять!!!!! Даже и не экспериментировал! Когда использовал "ifndef ..." - компелятор ругался о многократном включении. Вот и сформировалось у меня такое представление. А зависимость показана в реализации: файл ipo1.cpp Ну почему же? Если в *.h файле есть зависимость, то пусть он хэдер с этой зависимостью и подключает. |
Сообщ.
#12
,
|
|
|
Цитата agapUP @ Вот пример, стандартные библиотеки, типа #include <string> - у меня и в мыслях нет их в хедер загонять!!!! а это потому что ты не наследуешься от них. зафорвардить можно только классы, да и то только если будешь использовать указатели - так как они занимают фиксированный объём. ну еще енумы всякие. а если ты хочешь в хидере обьявить сам объект или наследоваться, то тогда надо делать инклюд, иначе компиль не знает сколько места надо выделить под эти объекты. |
Сообщ.
#13
,
|
|
|
Цитата 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 определяются в описании самого класса, хотя включение этой библиотеки осуществляется в ipo1.cpp!!! Чего? Если ты не подключишь string в хидер, но будешь его там использовать - будет ровно такая же ошибка. Цитата agapUP @ Когда использовал "ifndef ..." - компелятор ругался о многократном включении. Вот и сформировалось у меня такое представление. А зависимость показана в реализации: файл ipo1.cpp компилятор может ругатся о многократном включении, если отсуствуют гарды компиляции: #ifndef __SOME_HEADER_FILE__ //! гард предотвращающий повторное включение хидера. #define __SOME_HEADER_FILE__ //! Какие то объявления #endif |
Сообщ.
#14
,
|
|
|
agapUP
все указанные инклюды препроцесовр включает в файлы cpp, причем в каждый cpp, но повторов нет из-за #pragma once |
Сообщ.
#15
,
|
|
|
Доброе время суток
Цитата _lcf_ @ ...иначе компиль не знает сколько места надо выделить под эти объекты. Я не берусь судить, ибо не знаю! , но после этих строк мне чет зачесалось в пятой точке , что мои траблы связаны с выделением-затиранием память процесса ВОТ! Один проект! Два дочерних и один базовый: ... А скрины вставить не вышло..... Но там суть такая: для класса А я хидер базового включил в срр-файл класса А - и ошибки "С2504 - не определен базовый класс" не возникло! А для класса B - эта ошибка возникла! Добавлено Всем спасибо |