Search code examples
c++strategy-pattern

How to make a C++ class that inherits from only one of two base classes at compile time?


First time post.  This is a general question about how to do something in C++.  To not waste your time, I'll just ask it generalized.  But if your response is something like, "Why do you want to do something so stupid like that?", I'll give the details below.

General Question

I have a base class with common code (SPIBase).  I have two classes that inherit it that have significantly different implementations (SPIMaster, SPISlave).  In each of these two classes, I expose public/protected functionality that is identical.  I want to write a single class that optionally inherits from one of these two classes.  How should I go about doing that?

Details

I am building a library for some microelectronics (ESP8266).  I use the Arduino IDE, and the library is in C++.  As you might be familiar, SPI is a methodology/protocol for communicating between two micro-controllers or a micro-controller and something like a sensor.  A micro-controller is always a Master and the other device/sensor is always a Slave.  The Master completely controls the communication process in SPI.  The Slave is normally relatively passive.   I've written the library to work only between two ESP8266 micro-controllers to form a TCP/IP like protocol where either can send a message to the other un-solicited.  Basically, the Master/Slave issues are hidden and the developer using the library can setup their protocol any way they prefer and in either direction.  (i.e.  Client/Server/Peer messaging, send/response, Streams, etc).  Although, Master/Slave issues are hidden, obviously, one ESP8266 must use one base implementation and the other ESP8266 must use the other.

I now want to write the layer that implements Streams / File transfers.  This class will ride on one or the other of the two intermediate classes, but will be identical except in which class they inherit.  They both will be both senders and receivers.  I'd rather not have two complete classes that are really identical in their implementation.  In this case, I don't really want any portion of one chain of code to be on the other device.  My original thought proved after research not to be possible was to basically... have the library using developer use #define MASTER or #define SLAVE in their main program file and the streaming class would inherit one or the other classes based on this.  I soon discovered that #defines aren't visible downstream.   Is there some C++ design methodology / pattern that will get the results I want?   Thanks for your time.


Solution

  • You can use templates. For example:

    template <typename SPIImpl>
    class SPIStream : public SPIImpl
    {
        // stream implementation using the common interface
    };
    

    You would then declare an instance of the class like this:

    SPIStream<SPIMaster> spi_master_stream;
    

    OR

    SPIStream<SPISlave> spi_slave_stream;