【问题标题】:Having pointer to a template base class具有指向模板基类的指针
【发布时间】:2015-08-31 09:13:57
【问题描述】:

在下面的代码中,我有一个名为IDecoder 的接口,它应该由任何解码器类实现(此处为DecoderADecoderB)。 IDecoder 中有一个bitset<>,因此我将IDecoder 设为模板类,bitset 的大小在派生类中确定。我还有一个 Container 类,它应该包含一个指向 IDecoder 类的指针,但是由于 IDecoder 不是一个完整的类型,我添加了一个虚拟的 DecoderBase 类,IDecoder 从中继承:

#include <iostream>
#include <bitset>

class DecoderBase
{
public:
    DecoderBase(){}
    virtual ~DecoderBase(){}
};

template<size_t nb>
class IDecoder : public DecoderBase
{
public:
    IDecoder(){}
    virtual ~IDecoder(){}
    virtual std::bitset<nb> GetDecodedFields() = 0;
};

const int DecoderAMaxFields = 100;
const int DecoderBMaxFields = 200;

class DecoderA : public IDecoder<DecoderAMaxFields>
{
public:
    DecoderA(){}
    ~DecoderA(){}
    std::bitset<DecoderAMaxFields> GetDecodedFields()
    {
        std::bitset<DecoderAMaxFields> bits;
        // assume we've decoded fileds number 1 and 10 here
        bits[1] = 1;
        bits[10] = 1;
        return bits;
    }
};

class DecoderB : public IDecoder<DecoderBMaxFields>
{
public:
    DecoderB(){}
    ~DecoderB(){}
    std::bitset<DecoderBMaxFields> GetDecodedFields()
    {
        std::bitset<DecoderBMaxFields> bits;
        // assume we've decoded fileds number 11, 29, 110 & 142 here
        bits[11] = 1;
        bits[29] = 1;
        bits[110] = 1;
        bits[142] = 1;
        return bits;
    }
};

class Container
{
public:
    Container(){}
    virtual ~Container(){}
    void SetDecoder(DecoderBase* decoder)
    {
        mDecoder = decoder;
    }
    DecoderBase* GetDecoder()
    {
        return mDecoder;
    }
private:
    DecoderBase* mDecoder;
};

int main()
{
    Container container;
    container.SetDecoder(new DecoderA());
    ((DecoderA*)container.GetDecoder())->GetDecodedFields();
    return 0;
}

如您所见,在调用GetDecodedFields() 之前,我必须将其转换为其中一个解码器,这与多态的目的完全相反!如何修复此代码?我也考虑过使用boost::dynamic_bitset,但我不想使用它,因为它比正常的bitset 慢。

【问题讨论】:

  • 您想要实现什么(功能上)(bitset 是用来做什么的)?
  • Container使用什么样的Decoder是运行时信息,而bitset的大小必须在编译时声明。这两个概念不能一起工作。你应该考虑使用vector&lt;bool&gt;
  • BTW:std::bitset&lt;100&gt;std::bitset&lt;200&gt; 的类型不同。没有可以用作基类的类型std::bitset。这不是模板的工作方式。所以DecoderBase无法知道你要返回哪些类型。
  • dynamic_bitset 不可避免地会稍微慢一些——但这对你的目的真的很重要吗?它看起来确实是解决您的问题的最简单方法。
  • @bobah 我需要这个 bitset 进行按位运算,以便我可以快速知道哪些字段已被解码。

标签: c++ templates polymorphism bitset


【解决方案1】:

编辑:这个答案是对问题下的 cmets 的补充。

  • Container 使用什么样的 Decoder 是运行时信息,而 bitset 的大小必须在编译时声明。这两个概念不能一起工作。您应该考虑使用矢量。
  • 顺便说一句:std::bitset 和 std::bitset 的类型不同。没有类型 std::bitset 可以用作基类。这不是模板的工作方式。所以 DecoderBase 无法知道你要返回哪些类型。

在这种情况下如何使用std::vector&lt;bool&gt;而不是固定大小的std::bitset&lt;N&gt;的示例:

#include <iostream>
#include <bitset>
#include <vector>

class DecoderBase
{
public:
    DecoderBase() {}
    virtual ~DecoderBase() {}
    virtual std::vector<bool> GetDecodedFields() = 0;
};

class DecoderA : public DecoderBase
{
public:
    DecoderA() {}
    ~DecoderA() {}
    std::vector<bool> GetDecodedFields()
    {
        // assume we've decoded fileds number 1 and 10 here
        std::vector<bool> bits(100, false);
        bits[1] = true;
        bits[10] = true;
        return bits;
    }
};

class DecoderB : public DecoderBase
{
public:
    DecoderB() {}
    ~DecoderB() {}
    std::vector<bool> GetDecodedFields()
    {
        // assume we've decoded fileds number 11, 29, 110 & 142 here
        std::vector<bool> bits(200, false);
        bits[11] = 1;
        bits[29] = 1;
        bits[110] = 1;
        bits[142] = 1;
        return bits;
    }
};

class Container
{
public:
    Container() {}
    virtual ~Container() {}
    void SetDecoder(DecoderBase* decoder)
    {
        mDecoder = decoder;
    }
    DecoderBase* GetDecoder()
    {
        return mDecoder;
    }
private:
    DecoderBase* mDecoder;
};

int main()
{
    Container container;
    container.SetDecoder(new DecoderA());
    container.GetDecoder()->GetDecodedFields();
    std::cout << container.GetDecoder()->GetDecodedFields().size() << std::endl;
    return 0;
}

【讨论】:

  • 嗯,vector&lt;bool&gt; 的界面与 std::bitset 完全不同。
  • @πάνταῥεῖ 是的。但是,如果Decoders 的位集大小不同,他尝试做的事情是不可能用std::bitset 完成的。
  • 我没有看到这个。然后我不明白昨天的答案有什么问题。
【解决方案2】:

这里的问题不是多态性。

您正在使用异构容器。

在 C++ 中没有构造可以在不使用强制转换的情况下访问此类容器的元素。

干净的方法是对容器元素进行 dynamic_cast 以将元素转换为它们各自的类型。

【讨论】:

    猜你喜欢
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 2011-05-03
    相关资源
    最近更新 更多