Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Перекрёстные ссылки в C++  (Прочитано 6957 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Malamut

  • Автор темы
  • Ubuntu Member
  • Администратор
  • Старожил
  • *
  • Сообщений: 3337
  • Я добрый, честно!
    • Просмотр профиля
    • Моя страница на Launchpad
Перекрёстные ссылки в C++
« : 27 Июня 2009, 14:37:53 »
В общем, столкнулся с весьма странной проблемой. Есть у меня несколько классов, хочется чтоб в каждом классе были ссылки на объекты других и кроме того каждый класс жил в отдельной паре .h-.cpp файлов. Естественно, в заголовочных файлах прописываются #ifndef'ы, с этим всё путём. Но трабл в том, что несмотря на то, что все необходимые файлы вовсюда включены в некоторых местах компилятор не видит объявлений классов, в компиляторах майкрософта ЕМНИП это побароволось добавлением
extern class ClassNameОднако g++ такого не понимает и выдаёт ошибку, мол класс не может быть extern. Для примера:
//Class1.h

#ifndef CLASS1_H_
#define CLASS1_H_

#include "Class2.h"

class Class1 {
   Class2* cl;         //тут всё хорошо - никаких ошибок нет
}

#endif
//Class2.h

#ifndef CLASS2_H_
#define CLASS2_H_

#include "Class1.h"

class Class2 {
   Class1* cl;         //а вот тут ошибка - говорит что не знает что такое Class1
}

#endif
Вопрос: как такое побороть по науке? Сразу скажу - свалить все объявления в один .h файл не вариант, потому что в реальном проекте несколько огромных классов, нужно именно понять как ткнуть компилятор в факт того, что класс на самом деле объявлен.
"Носителем суверенитета и единственным источником власти в Российской Федерации является ее многонациональный народ" Конституция РФ

Оффлайн Protopopulus

  • Старожил
  • *
  • Сообщений: 1695
  • А чего вы так смотрите?..
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #1 : 27 Июня 2009, 14:42:31 »
С Си не знаком, но могу предположить, что Class1 является потомком Class2, а если это так, то, ИМХО, родительский класс не может быть наследником своих потомков... Ну, или как-то так :D
Если ты владеешь знаниями, то и знания владеют тобой. (с) Protopopulus

Оффлайн Malamut

  • Автор темы
  • Ubuntu Member
  • Администратор
  • Старожил
  • *
  • Сообщений: 3337
  • Я добрый, честно!
    • Просмотр профиля
    • Моя страница на Launchpad
Re: Перекрёстные ссылки в C++
« Ответ #2 : 27 Июня 2009, 14:51:47 »
С Си не знаком, но могу предположить, что Class1 является потомком Class2, а если это так, то, ИМХО, родительский класс не может быть наследником своих потомков... Ну, или как-то так :D
??? Ничего не понял, что хотелось сказать, но с С++ ты явно не знаком))

Кстати, если скидывать все объявления в один .h файл, то для разрешения видимости перекрёстных ссылок достаточно добавить в начало файла просто пустые объявления классов по типу
class Class1;НО! Если реальное определение находится в другом файле, то такая штука не прокатит. Так вот вопрос: как побороть?
"Носителем суверенитета и единственным источником власти в Российской Федерации является ее многонациональный народ" Конституция РФ

Оффлайн SergeyIT

  • Зануда.
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 5743
  • Все по палатам!
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #3 : 27 Июня 2009, 17:46:21 »
class Class1;
А почему не прокатит? Я обычно так и определяю, если в хидере только указатели на Class1.
А в class2.cpp включаю хидер Class1.h
Извините, я все еще учусь

Оффлайн SkeL2007

  • Участник
  • *
  • Сообщений: 204
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #4 : 27 Июня 2009, 17:57:12 »
Ну все очевидно, в общем. Так как инклюд просто вставляет содержимое хидера вместо себся. то будет вот что:

class Class2 {
   Class1* cl;         // Конечно не знает, он ниже объявлен;)
}

class Class1 {
   Class2* cl;         
}

А вот решение нормально сходу придумать что-то не получается

Оффлайн ubuntar

  • Участник
  • *
  • Сообщений: 129
  • Qui quaerit, reperit
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #5 : 27 Июня 2009, 18:43:50 »
Всё работает.
// main.cpp
#include <iostream>
#include "bb.h"

using namespace std;

int main()
{
    cout << "Hello world!" << endl;
    return 0;
}
// aa.h
#ifndef AA_H_INCLUDED
#define AA_H_INCLUDED

class Class1;
class Class2 {
  Class1* cl;         //а вот тут ошибка - говорит что не знает что такое Class1
};

#endif // AA_H_INCLUDED
// bb.h
#ifndef BB_H_INCLUDED
#define BB_H_INCLUDED

#include "aa.h"
class Class1 {
   Class2* cl;         //тут всё хорошо - никаких ошибок нет
};

#endif // BB_H_INCLUDED
Проблема может возникнуть(точно не знаю) если создавать объект класса Class2 раньше объекта класса 1.Тогда класс 2 не знает о реализации класса 1,а ему нужно создать объект.Так вроде.Но я где-то видел решение с шаблонами,только не помню,где.
« Последнее редактирование: 27 Июня 2009, 18:47:52 от ubuntar »

Оффлайн maximum2000

  • Активист
  • *
  • Сообщений: 403
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #6 : 27 Июня 2009, 21:25:09 »
Хм. Я в таких случаях понимаю что ошибся при проектировании.. и перепроектирую :) код.

Оффлайн mkarasik

  • Участник
  • *
  • Сообщений: 163
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #7 : 27 Июня 2009, 22:18:19 »
открыл файл, набросал код
class Class1;

class Class2
{
Class1* p;
};

class Class1
{
Class1* p;
};

int main()
{
}
Все скомпилировалось без проблем

Оффлайн SkeL2007

  • Участник
  • *
  • Сообщений: 204
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #8 : 27 Июня 2009, 22:41:50 »
mkarasik
Читаем внимательно, ага - ясен пень, что так все заработает. Проблема с заголовками.

Ну, в общем, единственное решение - в Class1.h перед инклюдом написать class Class1;
И в Class2.h - то же самое (для Class2, естественно)

maximum2000
Ну не согласен, бывают случаи, когда такое проектирование вполне логично

Оффлайн Yurror

  • Старожил
  • *
  • Сообщений: 1966
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #9 : 28 Июня 2009, 16:09:17 »
Когда ты пишешь заголовочники, тебе будет достаточно чтобы компилятор нашел имя данного класса. поэтому можно просто в начале заголовчника прописывать class A; class B; и т.д. по вкусу.

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

Сам не понял что сказал, но где-то так.  :D С++ еще та трава

Оффлайн mkarasik

  • Участник
  • *
  • Сообщений: 163
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #10 : 28 Июня 2009, 16:29:53 »
mkarasik
Читаем внимательно, ага - ясен пень, что так все заработает. Проблема с заголовками.


Как насчет пойти почитать о том, что делает #include, а потом умничать?

Оффлайн digiwhite

  • Активист
  • *
  • Сообщений: 732
  • http://www.welinux.ru
    • Просмотр профиля
    • http://www.welinux.ru
Re: Перекрёстные ссылки в C++
« Ответ #11 : 28 Июня 2009, 16:41:25 »
Хм. Я в таких случаях понимаю что ошибся при проектировании.. и перепроектирую :) код.

ИМХО - такая ситуация абсолютно не значит, что неграмотно выполнено проектирование. Насколько я помню, то в Qt такой способ отчасти был рекомендован для использования в некоторых случаях.
Социальная сеть не фанатично настроенных Linuxойдов - http://www.welinux.ru

Оффлайн unimix

  • Активист
  • *
  • Сообщений: 537
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #12 : 28 Июня 2009, 17:11:04 »
Ну, в общем, единственное решение - в Class1.h перед инклюдом написать class Class1;
И в Class2.h - то же самое (для Class2, естественно)

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

//Class1.h

#ifndef CLASS1_H_
#define CLASS1_H_

#include "Class2.h"

class Class2;
class Class3;
class Class1 {
   Class2* cl2;
   Class3* cl3;
}

#endif

//Class2.h

#ifndef CLASS2_H_
#define CLASS2_H_

#include "Class1.h"

class Class1;
class Class2 {
   Class1* cl1;
}

/* ... */

class Class1;
class Class3 {
   Class1* cl;
}

#endif

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

Оффлайн maximum2000

  • Активист
  • *
  • Сообщений: 403
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #13 : 29 Июня 2009, 00:04:04 »
#ifndef CLASS1_H_
#define CLASS1_H_
.....
#endif

согласен, я пишу это уже машинально лет 6 :)

Оффлайн Yurror

  • Старожил
  • *
  • Сообщений: 1966
    • Просмотр профиля
Re: Перекрёстные ссылки в C++
« Ответ #14 : 29 Июня 2009, 05:59:04 »
http://www.rsdn.ru/forum/cpp/3445472.aspx по теме.
Думаю там шанс получить квалифицированный ответ выше.

 

Страница сгенерирована за 0.019 секунд. Запросов: 21.