idanshmu
idanshmu

Reputation: 5261

c++ connect interface to base class

I have a problem in my design.

/// 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
};

The error is of course correct. no surprise there. But I need a solution. how to resolve this compilation error.

I have 4 suggestions:

  1. Use reinterpret_cast Operator in function myNode::add()
  2. Create an intrface INode and let ImyNode extend this INode
  3. Change ImyNode::add(ImyNode* v) to ImyNode::add(myNode* v)
  4. Let ImyNode extend Node

All 4 suggestions are unacceptable to me. Why?

  1. Won't work. ugly. Bad idea
  2. What if I don't own Node? what if class hierarchy is more complex then that?
  3. Interface should NOT know anything about its derived classes
  4. Don't like it that an interface extends non-interface class. Even if I do go this path, how would I call Node CTOR without ImyNode CTOR

If anyone has a better design or an elegant solution or can convince me one of my suggestion is good, please do.

Thanks.

Upvotes: 2

Views: 249

Answers (2)

PiotrNycz
PiotrNycz

Reputation: 24412

In your very design, you should use some kind of visitor pattern, I mean put all derived nodes in your interface. Other solution is to use dynamic cast and/or some adapter from ImyNode to Node. Like that:

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

As you can see adding of ImyNode to ImyNode is not possible here, you should know what you are doing. If there is no more specialization than myNode then get rid of your interface, since it turns out to be useless.

Upvotes: 1

n. m. could be an AI
n. m. could be an AI

Reputation: 119877

Your hierarchy is broken, you need to re-think it.

What if someone extends ImyNode in a way you did not expect

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

and then calls your myNode::add?

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

You will not be able to fulfill your obligation then.

Update

If you assume that every ImyNode is ultimately also a Node, then the simplest way to fulfill the obligation is to change the signature of 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.

};

Upvotes: 1

Related Questions