xaviersjs
xaviersjs

Reputation: 1737

Subclass object as a parameter to a virtual function

Ok, so basically I have a class in use in another class which, among other things, asks on object to report on its relationship to another object of the same type. Works great. FYI this class represents a protocol. Unfortunately, now I'm trying to decorate the class relationship by adding a class called a Wrapper. The main power of this class is that it can take the first class as an argument (or anything else that does the same).:

template< class InnerInterpreter >
class WrapperInterpreter
{
public:
    WrapperInterpreter(const InnerInterpreter &m) : innerMessage(m) {}

    ...

    virtual bool respondsToMessage(const WrapperInterpreter<InnerInterpreter> &) const = 0;

public:
    //member
    InnerInterpreter innerMessage;
};

What I've concluded for other design reasons is that having this as a base class to a set of wrappers (rather than taking two different protocols as arguments) allows me a combinatorial set of outer and inner protocol classes.

So here's my problem: When I try to subclass WrapperInterpreter<>, and in particular provide an implementation to respondsToMessage(), I end up with a subclass that is able to compare to any class in the WrapperInterpreter heirarchy. But that's not actually what I want to do. What I would like to do is to force the subclass to implement a method thusly:

template< class Inner >
class ConcreteWrapper : WrapperInterpreter<Inner>
{
    ...
    bool respondsToMessage(const ConcreteWrapper<Inner> &);
    ...
}

One solution I came to immediately was to simply remove it from the interface of WrapperInterpreter and just let the compiler complain about the missing interface method only when in use with the rest of the design.

So my question is: is there any way to put a method in an abstract class's interface, such that the subclass must take an object of the subclass type as a parameter?

Alternatively, am I trying to use inheritance incorrectly? Does anybody have any useful design patterns that might help me to address this problem?

Upvotes: 2

Views: 306

Answers (1)

Matthieu M.
Matthieu M.

Reputation: 299810

There is a design called CRTP (Curiously Recurring Template Pattern) which consists in passing the type of the Child to the Parent as a template parameter:

template <typename Child>
class WrapperInterpreter {
    using Inner = typename Child::Inner; // nested typedef

    WrapperInterpreter(Inner const& ...);

    virtual bool respondsToMessage(Child const& ...) = 0;
};

template <typename Inner>
class Concrete: public WrapperInterpreter< Concrete<Inner> > {

    virtual bool respondsToMessage(Concrete const& ...) override;

};

Upvotes: 1

Related Questions