Yggdrasil
Yggdrasil

Reputation: 53

Efficient alternativ to Interfaces in C++

In C++ I have one class it exposes two (or more) different overlapping interfaces. It is a central data storage and signal provider.

Abstract very simplified example, in reality there would be many more getter and setters:

class IXY
{
public:
   virtual int GetX(int) = 0;
   virtual int GetY(int) = 0;
}

class IX
{
public:
  virtual int GetX(int) = 0;
}

class A : public IX, IXY
{
    // ... implement getter and others
}

On the other side I have two other classes, each needing access to one of the interface only, to prevent accidental unjustified to data it should not use. They will only get the interface pointer and will only access this specified interface. However, if there are many different overlapping interfaces and memory critical embedded systems a virtual function table is not really wanted. With luck a compiler could optimize it away but there is no guarantee.

Is there something else one could do, some nice design pattern? I only could think of ugly defines modifying visibility (private, public) of the the getters for different includes, but this is not really nice. Or using defines to either use the interface for static testing that only required interfaces are used, and not using interfaces at all for the real compile step.

Upvotes: 0

Views: 412

Answers (2)

Adrian McCarthy
Adrian McCarthy

Reputation: 47954

Class A could have a completely private interface and declare IX and IXY as friends.

class A {
  private:
    int GetX() { return m_x; }
    int GetY() { return m_y; }
    int m_x;
    int m_y;
    friend class IX;
    friend class IXY;
 };

Instead of being abstract interfaces, IX and IXY could be implementations that maintain a reference or pointer to the instance of class A and provide the functionality.

 class IX {
   public:
     explicit IX(A &a) m_a(a) {}
     int GetX() { return m_a.GetX(); }

   private:
     A &m_a;
 };

 // similar for IXY

The implementations for common methods are effectively shared. The simple forwarding methods in the "interfaces" will likely be optimized away to direct calls to the appropriate method in A. There still might be an indirection, and you might just be trading off code space for vtable space, but it does give a nice way to control the interfaces offered to other objects.

Upvotes: 1

Jens
Jens

Reputation: 9406

When you do not need the dynamic dispatch at runtime but can specify the actual type at compile time, you could stick to static polymorphism. There are at least three ways to do static polymorphism.

  • Make the client classes template classes and then pass them your objects.
  • Curiously recursive template pattern (CRTP)
  • Use a functional programming approach and let the client take std::function objects. Instead of defining two abstract interfaces, one with member function f and another one with member function g for each client, pass each client a std::function parameter which then calls the member function on the object.

Upvotes: 0

Related Questions