Работа с круговой зависимостью от наследования - PullRequest
2 голосов
/ 27 февраля 2012

Я собираюсь перейти на C ++ über n00b и спросить, как лучше всего справиться с циклической зависимостью, когда у вас есть наследование.

Набор прост: класс сцены расширяет Actor;Сцена имеет указатель на вектор актеров;У актера есть указатель на (родительскую) сцену.

Что касается включаемых файлов, которые я получил:

Scene.h:

#include <string>
#include <vector>
using namespace std;

#ifndef __Scene_h__
#define __Scene_h__

#include "Actor.h"

namespace myns
{
    // class Actor;
    class Scene;
}

namespace myns
{
    class Scene: public myns::Actor
    {
        /* private class attributes... */

        public:
            /* public class attributes... */

            std::vector<myns::Actor*> actors;

            Scene(/* arguments */);

            /* public class methods... */
    };
}

#endif

Actor.h

#include <string>
#include <vector>
using namespace std;

#ifndef __Actor_h__
#define __Actor_h__

#include "Scene.h"

namespace myns
{
    // class Scene;
    class Actor;
}

namespace myns
{
    class Actor
    {
        /* private class attributes... */

        public:
            /* public class attributes... */

            myns::Scene* scene;

            Actor();

            Actor(/* arguments */);

            /* public class methods... */
    };
}

#endif

Но это дает мне много ошибок C2504 / базовый класс не определен в Visual Studio 2010.

Если я прокомментирую включение Scene.h в Actor.h и раскомментирую предварительное объявление Scene в Actor.h это работает, но затем, в моем приложении, если я хочу включить только Actor.h в определенный фрагмент кода, это не будет работать.Как я могу заставить это работать, сохраняя независимость включения для Actor.h - включая Actor.h без необходимости предварительно вручную включать Scene.h?

Что не так с моими определениями классов и как лучшеспособ справиться с этой циклической зависимостью?

Разве директивы #ifndef не должны предотвращать эту проблему включения?

Заранее спасибо.

Ответы [ 2 ]

6 голосов
/ 27 февраля 2012

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

Что вам нужно сделать, это вфайл .cpp, в котором вам нужно использовать определить класс Actor, который вы должны include и Actor.h и Scene.h.Таким образом, предварительное объявление будет разрешено, и все должно работать.

Кроме того, вы должны переместить свои #ifndef и #define прямо в верхнюю часть файла, до include s.Кроме того, наличие using в заголовочном файле является плохой практикой, поскольку другие файлы, которые include вашего заголовка, могут работать неправильно.Это должно быть нормально, чтобы положить его в ваш namespace myns { ... } хотя.

1 голос
/ 27 февраля 2012

Является ли сцена действительно тип актера?

Если это так, актеры, вероятно, не должны знать о сценах. Базовые классы обычно не должны знать о своих производных классах.

Где здесь принцип замены Лискова ? Какое действие вы выполняете над актером, который по-разному будет полиморфно выполняться сценой.

В любом случае Scene является производным от Actor, поэтому должен включать его базовый класс. Но в Actor.h, если вам действительно нужен класс Scene, это должна быть только предварительная декларация.

В единицах компиляции (файлы .cpp) вы можете включить оба заголовка, если это необходимо.

...