C++ 具有指向模板基类的指针
在下面的代码中,我有一个名为IDecoder的接口,它应该由这里的任何解码器类DecoderA和DecoderB实现。IDecoder中有一个位集,因此我将IDecoder作为模板类,位集的大小在派生类中确定。我还得到了一个容器类,它应该包含一个指向IDecoder类的指针,但由于IDecoder不是一个完整类型,我添加了一个伪DecoderBase类,IDecoder从中继承:C++ 具有指向模板基类的指针,c++,templates,polymorphism,bitset,C++,Templates,Polymorphism,Bitset,在下面的代码中,我有一个名为IDecoder的接口,它应该由这里的任何解码器类DecoderA和DecoderB实现。IDecoder中有一个位集,因此我将IDecoder作为模板类,位集的大小在派生类中确定。我还得到了一个容器类,它应该包含一个指向IDecoder类的指针,但由于IDecoder不是一个完整类型,我添加了一个伪DecoderBase类,IDecoder从中继承: #include <iostream> #include <bitset> class D
#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_位集,但我不想使用它,因为它比普通位集慢。编辑:这个答案是对问题下的注释的补充
容器使用哪种解码器是运行时信息,而位集的大小必须在编译时声明。这两个概念不能一起工作。你应该考虑使用向量。
顺便说一句:std::bitset和std::bitset的类型是不同的。没有可以用作基类的类型std::bitset。模板不是这样工作的。所以DecoderBase无法知道要返回哪些类型。
在本例中,有关如何使用std::vector而不是固定大小的std::Bitset的示例:
#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;
}
这里的问题不是多态性 您正在使用一个异构容器 <>没有C++的构造来访问容器的元素而不使用强制转换。< /P>
干净的方法是对容器元素进行动态强制转换,以将元素强制转换为其各自的类型。从功能上讲,您试图实现什么样的位集?容器使用什么样的解码器是运行时信息,而位集的大小必须在编译时声明。这两个概念不能一起工作。您应该考虑使用vector.BTW:std::bitset和std::bitset的类型是不同的。没有可以用作基类的类型std::bitset。模板不是这样工作的。所以DecoderBase无法知道您想要返回哪种类型。dynamic_位集不可避免地会稍微慢一点——但这对您的目的真的很重要吗?它看起来确实是解决您问题的最简单的方法。@bobah我需要这个位集来进行逐位操作,这样我就可以快速知道哪些字段已被解码。vector与std::bitset有一个非常不同的接口。@πάνταῥεῖ 是的。但是,如果解码器的位集大小不同,他试图用std::bitset做的是不可能的。你应该知道,。我没有看到这个。那么我不明白昨天的答案有什么问题。