binyamina
binyamina

Reputation: 193

Design an interface with appropriate declarations of Base class pointers - cpp

I have a little design problem.

Assume I have this interface:

class IBase {
public:
    virtual void Run() = 0;
    virtual void DoSomethingWithData(IData* data) = 0;
    virtual ~IBase() = 0;
};

I want to implement derived classes, so I need to build a derived class for IData (let's call it DData). IData is basically an empty interface:

class IData {
public:
    IData();
    virtual ~IData() = 0;
};

The problem is that in DoSomethingWithData method that I implement - I need to refer to specific members in DData, but I can't because the pointer is of IData . For example, see implementation of DoSomethingWithData in some derived class:

class DData : public IData {
private:
    int m_i;
};

<Derived.h : IBase>
Derived::DoSomethingWithData(IData* data) {
    some_function_call(data->m_i) // cannot be used by the base ptr
}

What is the best way to overcome this problem?

dynamic cast on SetData? Changing the interface (in this way?)? Other option?

Edit:

To clarify the problem: I have this relation -

class A -> uses DataA
class B -> uses DataB
class C -> uses DataC

there is a common interface for the classes: Run, DoSomethingWithData. DoSomethingWithData expects for data, but it does not know what is the data, it depends in the class that we implement. I need to find the best way to write the interface, without using bad OOP techniques like dynamic_cast.

Upvotes: 2

Views: 320

Answers (3)

binyamina
binyamina

Reputation: 193

The solution which we chose is using templates (I don't understand why no one suggested it).

template <class T>
class IBase {
public:
    virtual void Run() = 0;
    virtual void DoSomethingWithData(const T& data) = 0;
    virtual ~IBase() = 0;
};

I think that this is the best solution in this case, since it does not requires anyone to derive from empty interface, and it does declare for some contruct.

I'd like to hear if someone has any reservation for this solution.

Upvotes: 0

jfMR
jfMR

Reputation: 24778

The problem is that in DoSomethingWithData method that I implement - I need to refer to specific members in DData, but I can't because the pointer is of IData.

You are passing a pointer to IData which is the base class of DData. By means of virtual function dispatch you may call a member function that is is actually implemented in DData through a pointer to IData.

The class DData derives from IData, so you can declare a virtual member function in IData:

class IData {
public:
    IData();
    virtual int getData() = 0; // <-- new virtual function
    virtual ~IData() = 0;
};

and then implement this function in DData:

class DData : public IData {
public:
    int getData() override { // <-- implementation
       return m_i;
    }
private:
     int m_i;
};

Since this member function is implemented in DData, it can access its private data members (i.e.: m_i).

When you call getData() of a DData instance through a IData pointer, you will be using DData's implementation.

Upvotes: 1

user167921
user167921

Reputation: 330

I need to refer to specific members in DData, but I can't because the pointer is of IData

Interfaces specify a contract. It does not "know" about internal details/representation (aka, things like member variables, private functions, etc.) If your IData has to "know" about private member variables of DData, you are doing something wrong. Perhaps using an interface for Data is wrong. If Data is meant to be a POD (plain ol' data) struct, then just have your base class take a Data and expose an API that deals with said struct.

Upvotes: 1

Related Questions