2013-04-15 4 views
2

У меня проблема в моем дизайне.C++ интерфейс подключения к базовому классу

/// Generic class. Not owned by myself 
class Node 
{ 
    add(Node* v) { /* do somthing */ } 
}; 

/// interface writtern by myself 
class ImyNode 
{ 
    add(ImyNode* v) = 0; 

    /// More functions 
}; 

/// Implement ImyNode, use Node for implementation of SOME functions. 
class myNode: 
    public ImyNode, 
    public Node 
{ 
    add(ImyNode* v) { Node::add(v); } // Error: ImyNode is not a type of Node 
}; 

Ошибка, конечно, правильная. неудивительно. Но мне нужно решение. как решить эту ошибку компиляции.

У меня есть 4 предложения:

  1. Использование reinterpret_cast оператора в функции MyNode :: добавить()
  2. Создать intrface INode и пусть ImyNode продлить этот инод
  3. Изменить ImyNode :: добавить (ImyNode * v) в ImyNode :: добавить (MyNode * v)
  4. Пусть ImyNode простираться Сев.Узел

Все 4 предложения неприемлемы для меня. Зачем?

  1. Не сработает. некрасиво. Плохая идея
  2. Что делать, если я не владею узлом? что, если иерархия классов более сложна тогда?
  3. Интерфейс не должен знать ничего о его производных классах
  4. Не нравится, что интерфейс расширяет класс без интерфейса. Даже если я сделаю этот путь, как бы я назвал Node CTOR без ImyNode CTOR

Если у кого-то есть лучший дизайн или элегантное решение или может убедить меня, что одно из моих предложений хорошее, пожалуйста.

Спасибо.

+0

Если класс ÌmyNode' является интерфейсом, почему бы не позволить 'Node' наследовать от этого и ваш' myNode' только наследовать от 'Node'? –

+0

Узел - это общий класс, который обычно не принадлежит мне (давайте предположим на секунду, что я бы хотел избежать любых изменений в узле, поскольку он не является собственным и слишком общим. ImyNode имеет некоторые конкретные функции, которые не должны быть связаны с общим узлом (или должен знать) – idanshmu

+1

Если вы хотите использовать Node, тогда класс myNode должен содержать «Node» (должен быть Is-a), а не наследовать от него. – Arun

ответ

1

Ваша иерархия сломана, вам нужно ее переосмыслить.

Что делать, если кто-то проходит ImyNode таким образом, вы не ожидали

class IUnexpectedNode : public ImyNode {}; // note: not inheriting Node 

, а затем вызывает ваш myNode::add?

IUnexpectedNode unexpected; 
myNode my; 
my.add(unexpected); 

Тогда вы не сможете выполнить свои обязательства.

Update

Если предположить, что каждый ImyNode в конечном счете, также Node, то самый простой способ выполнить обязательство, чтобы изменить подпись ImyNode::add().

class ImyNode 
{ 
    virtual void add(Node*) = 0; // This method follows the Node::add(Node*) 
           // signature, although the classes are unrelated. 
           // The intent is that each class that implements 
           // ImyNode also extends Node, so the two methods 
           // merge into one. 

}; 
1

В вашем дизайне вы должны использовать какой-либо шаблон посетителя, я имею в виду, что все производные узлы в вашем интерфейсе. Другим решением является использование динамического преобразования и/или некоторого адаптера из ImyNode в Node. Как что:

class myNode; 
    class someOtherNode; // if any. 
    class ImyNode { 
    public: 
    virtual void add(myNode* node) = 0; 
    virtual void add(someOtherNode* node) = 0; 
    }; 

Как вы можете видеть добавление ImyNode к ImyNode не возможно здесь, вы должны знать, что вы делаете. Если больше нет специализации, чем myNode, тогда избавьтесь от своего интерфейса, поскольку он оказывается бесполезным.

Смежные вопросы