C ++多态接口

时间:2014-06-11 21:43:32

标签: c++ inheritance polymorphism

我试图创建一种处理协议的许多不同版本的方法,类似于问题How to handle different protocol versions transparently in c++?。我同意一系列继承可以很好地解决问题。

这就是我在Java中的方法:创建一个IParser接口,并有几个ParserV0ParserV1,...类,相互继承并实现{{ 1}}。

据我所知,由于一些多重继承和IParser技巧,在C ++中创建该结构是可能的。 这里的问题:在Java中,如果我想要一个解析器,我想,我可以说virtual。我会得到一些IParser parser = getCorrectVersion(...)等版本,实现ParserV0并调用我需要的方法。

与C ++中的最后一步相同的是什么?我似乎没有办法要求任何一个类实现另一个类,然后能够调用它的方法。

编辑:

这是我尝试做jtedit建议的事情,因为我在StackOverflow周围看到了类似的建议:

IParser

在我的代码的另一部分,我说

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();
    }
};

我已经使用此代码及其变体获得了编译时错误,但这导致我提出这个问题。

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

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)

我不明白为什么我有第一个,但第二个是有点期待的,并且是我的问题中的主要关注点。

编辑2

我对Scis建议的尝试(代码声明类和函数是相同的)

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

这一次,我收到unique_ptr<IParser> getParser() { return unique_ptr<IParser>(new ParserV0()); } auto parser(getParser()); 查找错误,因为它似乎在vtable中查找函数定义。

最终编辑:

我意识到我的代码有点乱,我错过了一些参数修饰符,所以虚拟的和最重要的一个没有匹配。这些错误很有意义。谢谢你的帮助!

3 个答案:

答案 0 :(得分:3)

你的getCorrectVersion()函数需要返回一个指向接口的指针,即IParser

例如:

IParser* getCorrectVersion(int version){

    switch(version){
    case 0: 
         return new ParserV0();
    case 1:
         return new ParserV1();
    }
}

为了能够调用这些方法,您想要的方法必须在IParser中是虚拟的

例如:

class IParser{
public:
    virtual int getInt() = 0;
};

答案 1 :(得分:3)

您可以使用抽象基类并创建所需的函数virtual,如前所述,我建议使用unique_ptr而不是原始指针,这样您就不必完成使用后的delete内存(与Java中的内容类似):

这是一个示例:

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;
}

其中foo声明为:virtual void foo() = 0;。请参阅完整示例here

答案 2 :(得分:1)

您需要抽象工厂或参数化工厂方法;这是jtedit所描述的那种。通常在执行此操作时,您可以使构造函数本身受到保护,并且只显示工厂方法。有关更多信息,请查看Gang of Four Creational Patterns

http://en.wikipedia.org/wiki/Design_Patterns