c++多态接口

C++ Polymorphic Interfaces

本文关键字:接口 多态 c++      更新时间:2023-10-16

我试图创建一种方法来处理一个协议的许多不同版本,类似于如何在c++中透明地处理不同的协议版本?我同意继承链可以很好地解决这个问题。

这就是我在Java中如何做到的:创建一个IParser接口,并有几个ParserV0, ParserV1,…类,相互继承,实现IParser

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

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

编辑:

这是我尝试做jtedit所建议的,因为我在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();
    }
};

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

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)

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

我不太明白为什么我有第一个,但第二个是预料之中的,也是我问题中的主要关注点。

编辑2

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

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

这次,我得到了vtable查找错误,因为它似乎在寻找IParser中的函数定义。

最后的编辑:

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

您可以使用抽象基类并创建所需的函数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;

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

你需要一个抽象工厂,或者一个参数化工厂方法;这就是它所描述的。通常在这样做时,您使构造函数本身受到保护,并且只暴露工厂方法。查看四人组创建模式获取更多信息

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