C++多态接口

4
我正在尝试创建一种处理多个协议版本的方法,类似于问题如何在C++中透明地处理不同的协议版本?。 我同意使用继承链可以很好地解决问题。
这是我在Java中的做法:创建一个IParser接口,并拥有多个ParserV0ParserV1等实现IParser的类,这些类之间通过继承相互关联。
我知道由于某些多重继承和虚拟技巧,C ++中也可以创建该结构。但问题在于:在Java中,如果我想要一个解析器,我认为我可以说IParser parser = getCorrectVersion(...)。我将获得实现IParserParserV0的某个版本等,并调用我需要的方法。
那么在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

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

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

auto parser(getParser());

这次,我遇到了一个“vtable”查找错误,因为它似乎正在寻找在“IParser”中的函数定义。
最终编辑:
我意识到我的代码有点混乱,而且我缺少参数修饰符,所以虚拟的和重写的不匹配。这些错误很有道理。谢谢你的帮助!
3个回答

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

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;。完整的示例请参见此处


1
你需要一个抽象工厂或参数化的工厂方法,这就是jtedit所描述的。通常情况下,你会将构造函数设置为受保护状态,并仅公开一个工厂方法。请查看《设计模式》中的创建型模式以获取更多信息。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接