Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Polymorphic Interfaces

I'm trying to create a way to handle many different versions of a protocol, similar to the question How to handle different protocol versions transparently in c++?. I agree that a chain of inheritance would solve the problem well.

This is how I would do it in Java: create an IParser interface, and have several ParserV0, ParserV1, ... classes, inheriting from each other and implementing IParser.

I understand that creating that structure is possible in C++ due to some multiple inheritance and virtual tricks. Here's the catch: in Java, if I wanted a parser, I think, I would be able to say IParser parser = getCorrectVersion(...). I would get some version of ParserV0, etc., implementing IParser and call the methods I need.

What's the equivalent to that last step in C++? There doesn't seem to be a way for me to ask for any class implementing another and then being able to call its methods.

EDIT:

Here's my attempt at doing what jtedit has suggested, since I have seen similar suggestions around StackOverflow:

class IParser {
public:
    virtual const string doSomething(params) = 0;
};

class ParserPreVersion : public IParser {
public:
    const string doSomething(params) {
        // do some thing
    }
};

class ParserFactory {
...
public:
    const IParser* generateParser() {
        return new ParserPreVersion();
    }
};

In another part of my code, I say

const IParser parser = *(ParserFactory().generateParser());

I've been getting compile-time errors with this code and variations of it, though, leading me to ask this question.

In member function 'const IParser* generateParser()':
error: cannot allocate an object of abstract type 'ParserPreVersion'
note:   because the following virtual functions are pure within 'ParserPreVersion':
note:      virtual const std::string IParser::doSomething(params)

also

error: cannot declare variable 'parser' to be of abstract type 'const IParser'
note:   since type 'const IParser' has pure virtual functions

I don't understand exactly why I have the first one, but the second is somewhat expected, and was the main concern in my question.

EDIT 2

And my attempt at what Scis has suggested (code declaring classes and functions is the same)

unique_ptr<IParser> getParser() {
    return unique_ptr<IParser>(new ParserV0());
}

auto parser(getParser());

This time, I get a vtable lookup error, since it seems be looking for the function definition in IParser.

FINAL EDIT:

I realized my code was a little messy and I was missing some modifiers for parameters, so that the virtual one and the overriding one didn't match up. The errors make a lot of sense. Thank you for your help!

like image 777
bbill Avatar asked Mar 20 '23 08:03

bbill


1 Answers

You could use an abstract base class and create the required function as virtual as noted before the only thing I'd suggest is using unique_ptr and not raw pointers this way you'll not have to delete the memory yourself when you are finished using it (similarly to what you'd have in Java):

Here a sample:

unique_ptr<IParse> getParser(int x){
    switch (x){
        case 1:
            return unique_ptr<IParse>(new P1());
            break;
        case 2:
            return unique_ptr<IParse>(new P2());
            break;
    }
    return nullptr;
}

int main() {
    auto p1(getParser(1));
    p1->foo();

    auto p2(getParser(2));
    p2->foo();
    return 0;
}

where foo is declared as : virtual void foo() = 0;. See full example here.

like image 75
Scis Avatar answered Mar 25 '23 06:03

Scis