1. C++ / Говнокод #13457

    +7

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    namespace engine { namespace ui { class Console; } }
    
    class Dummy
    {
       engine::ui::Console * _ptr;
    };

    Решение проблемы с перекрёстными #include, когда классы должны хранить указатели друг на друга. Простое объявление class engine::ui::Console; не работает.
    Не в первый раз сталкиваюсь с этой проблемой из-за примитивной системы импорта.

    Запостил: an0nym, 20 Июля 2013

    Комментарии (18) RSS

    • Разделять классы на .hpp и .cpp - не умеете?
      Ответить
      • Причём здесь это?
        Ответить
        • Я сейчас плохо соображаю ночью.
          Но почти от всех форвард деклараций можно уйти, разделяя класс на реализацию и описание (цпп и хпп).

          //тут было много текста.
          Ответить
          • никогда такого не видел?
            struct a;
            struct b { a * ptr; };
            struct a { b * ptr; };
            как ему тут поможет то, о чем ты говоришь?
            Ответить
            • Да я и говорю, что по ночам плохо соображаю. Об этом подумал в посл. момент.
              Но вообще-то, если приходится такое городить - то это явно проблемы архитектуры приложения.
              Ответить
          • форварды - чудесная вещь. От них не надо уходить. Наоборот, чем чаще получается заменить полный инклюд на форвард, тем лучше. Полное определение типа нужно, только если зависимый класс содержит поле типа, наследуется от этого типа или вызывает его методы в хедере. Без форварда невозможен pimpl.
            Трудно представить, сколько времени компилился бы clang, если бы там все форварды заменили на инклюды...
            Ответить
    • фу мерзость
      мерзость в голых укаателях
      мерзость в том, что указатели друг на друга собираются хранить классы из явно несвязанных неймспейсов
      мерзость в больших буквах в названиях классов
      Ответить
      • Указателями связаны графическая консоль и интерпретатор, которому нужно посылать ввод и получать ответ.
        Стиль именования из Qt почерпнул, так ентерпрайзнее выглядит.
        Ответить
        • qt и ынтерпрайз - поделил на 0

          кроме forward declaration есть еще минимум 3 способа увязать классы
          Ответить
          • >>qt и ынтерпрайз - поделил на 0
            Словил SIGFPE и проигнорировал. У Qt логичный и обоснованный стиль оформления кода, в его сорцах чуточку приятнее копаться, чем в каком-нибудь boost.

            >>еще минимум 3 способа
            А какой же третий?
            Ответить
            • Когда-то давно мне было лень разделять классы на 2 файла и чтобы иметь сделать такое мне пришлось сделать первый класс шаблонным и при первой возможности затайпдефить.лол.
              Ответить
            • логичный и обоснованный стиль, в котором нет места неймспейсам, а конфликты имён обязаны разруливаться ебланскими Q-префиксами
              да?
              Ответить
              • Как минимум с версии 4.7 Qt можно сконфигурировать, указав опцию "-qtnamespace <namespace>", оборачивающую код библиотек в указанное пространство имен.
                >>ебланскими Q-префиксами
                OK, дальше явно спорить бессмысленно.
                Ответить
                • т.е. предлагается опционально обернуть _всю_ немаленькую библиотеку qt в _один_ неймспейс, сохранив раздражающие префиксы
                  ЕМНИП у moc (кстати, очередное гениальное творение - вставить лишнюю сущность в тулчейн, ибо ниасилили - такой типичный ентерпрайз бгг) были непреодолимые проблемы, если пользовательский класс с Q_OBJECT находился в "неправильном" неймспейсе
                  Ответить
            • > А какой же третий?
              1. интерфейс
              2. шаблон
              3. коллбек
              Ответить
        • > Указателями связаны графическая консоль и интерпретатор

          На кой ляд? Зачем привязывать модель к представлению? Зачем интерпретатору знать о консоли? А если я к вебу захочу его прикрутить?
          class repl
          {
              std::isream _in;
              std::osream _out;
              interpreter & _interpr;
          public:
              /* ... */
              void run()
              {
                  std::string input;
                  while (!_interpr.done()) {
                      _in >> input;
                      sdt::string resp = _interpr.eval(input);
                      _out << resp << sdt::endl;
                  }
              }
          };
          Ответить
    • namespace xui
      Ответить

    Добавить комментарий