Структура каталогов — классы файлов и папок должны знать друг друга?

Я столкнулся с проблемой, когда два класса знали друг друга, когда пытался создать структуру каталогов, подобную этой:

Пример структуры каталогов

Вот мой Base класс, который включает в себя общие элементы File а также Folder,
Обратите внимание, что я не учел методы получения и установки, конструкторы и деструкторы, #includeс и #defines и другие не связанные методы и атрибуты (= почти все) ради этого вопроса:

class Base {
private:
string m_name;
/* Both File and Folder have a parent,
* but the parent can only be a Folder */
Base* m_parent;
};

Вот класс Folder который работает просто отлично:

class Folder : public Base {
public:
virtual void addChild(Base* child);
virtual void removeChild(Base* child);
private:
vector<Base*> m_children;
};

А потом File В классе нет ничего нового (кроме некоторого материала, связанного с файлами, который не имеет отношения к моему вопросу, поэтому я их пропустил):

class File : public Base {
};

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

Base::Base(string name, Base* parent) { ... }
File::File(string name, Base* parent) { ... }
// parent should be of type Folder for Files too
Folder::Folder(string name, Folder* parent) { ... }

Проблема очевидна.
Прежде всего, родитель должен ВСЕГДА быть Folder, это не может быть File,
Тем не менее, я должен использовать Base поскольку File а также Base очевидно не могу знать Folder,

Кроме того, так как мой Base а также File не знаю Folderони не могут назвать это addChild(Base* child); метод:

File::File(string name, Base* parent)
: m_name(name), m_parent(parent)
{
if (parent) {
parent->addChild(this); // Base doesn't have addChild()-method
}
}

У меня болит голова от размышлений, как я могу обойти эту проблему?

РЕДАКТИРОВАТЬ: Я не хочу хакерский способ получить желаемый результат, я хочу найти ошибку в моем дизайне.
Как этот материал предназначен для Windows или Unix?

3

Решение

Попробуй это:

class Folder;

class Base {
protected:
Base(const string &name, Folder *parent);
private:
string m_name;
Folder *m_parent;
//no add or remove should go here
};

class Folder : public Base {
public:
Folder(const string &name, Folder *parent)
:Base(name, parent)
{
}
void addChild(Base* child);
void removeChild(Base* child);
/*...*/
};

class File : public Base {
public:
File(const string &name, Folder *parent)
:Base(name, parent)
{
}
};

inline Base::Base(const string &name, Folder *parent);
:m_name(name), m_parent(parent)
{
if (parent) {
parent->addChild(this); // no problem!
}
}
4

Другие решения

Других решений пока нет …