我正在尝试创建一个可以存储模板值的C ++ Template
类。但是,我需要在知道模板值的类型之前创建指向此类的指针。为此,我创建了一个模板类继承的抽象Base
类。我创建指向Base
的指针,当它们被分配时,我使用basePtr = new Template<TYPE>
。
此处的问题在于为Template
分配值。我能想到的每一种方式(我都喜欢使用重载赋值运算符)需要一个模板数据类型作为形式参数的方法。因为Template
个对象只能通过Base
指针访问,所以我必须在Base
中创建一个虚函数。但是,虚方法不能包含模板数据类型,Base
签名中的虚方法必须与Template
方法的虚方法匹配。
这是我想要的一个例子:
class Base {
public:
/* THIS IS ILLEGAL - can't have template virtual method
template <class V>
virtual void operator =(const V& newValue) = 0;
*/
};
template <class ValueType>
class Template : public Base {
private:
ValueType *value;
public:
void operator =(const ValueType& newValue) {
*value = newValue;
}
};
int main() {
Base *theObject; // Datatype for template not known
theObject = new Template<string>; // At this point, it will be known
// NOW, THIS DOESN'T WORK - no virtual assignment overload in Base
*theObject = "Hello, world!";
return 0;
}
如果我以完全错误的方式解决这个问题,我道歉,如果我的方法很愚蠢 - 这是我第一次涉足真正的OOD。我有没有办法解决这个问题?我知道我可以在Base
中创建一个很长的纯虚函数列表,它使用不同的输入类型重载赋值运算符,如下所示:
virtual void operator =(const string& newValue) = 0;
virtual void operator =(const int& newValue) = 0;
virtual void operator =(const long& newValue) = 0;
...
但是,我希望用户能够将自定义类对象(或更可能是指向这些对象的指针)插入到Template::value
中,而且我无法用上述方法完成。< / p>
答案 0 :(得分:1)
实现您要实现的目标的一种方法是使用Boost.Any(一个众所周知的仅限标头的库)。以下是演示。代码会逐步评论,因此您应该能够理解它,并且 here 是一个实例:
#include <stdexcept> // Standard header for exception classes
#include <string> // Standard header for std::string
#include <boost/any.hpp> // The Boost.Any library header
#include <iostream> // This program prints some output
class Base
{
public:
virtual void operator = (boost::any val) = 0;
// ^^^^^^^^^^
// This can hold (almost) "any" value
// You need a virtual destructor if you want to delete objects
// of subclasses of this class through a pointer to this class!
virtual ~Base() { }
};
template <class ValueType>
class Template : public Base
{
private:
ValueType value;
// ^^^^^^^^^
// I do not see why using a pointer in this case. Manual memory
// management just complicates things. However, if your really
// need to do it and your really know what you're doing, go ahead.
// Just remember to delete your pointer at destruction and not to
// dereference it before it points to an allocated object (in your
// original text, both of these things are NOT done correctly).
public:
virtual void operator = (boost::any val)
{
// Attempt a cast to detect if the value we are trying to
// assign to this object is of the appropriate type...
ValueType* pVal = boost::any_cast<ValueType>(&val);
if (pVal == nullptr)
{
// ...it is not! Throw an exception...
throw std::logic_error("Incompatible type");
}
// The value is OK: assign it...
value = *pVal;
}
};
int main()
{
Base *theObject;
theObject = new Template<std::string>;
try
{
// This assignment will succeed...
// Wrapping the string literal in a std::string object is necessary
// because boost::any cannot be initialized from an array (and in C++
// string literals are arrays of characters).
*theObject = std::string("Hello, world!");
// This assignment will fail!
*theObject = 1;
}
catch (std::logic_error const& e)
{
// Handle the exception...
std::cout << e.what();
}
delete theObject; // <=== DON'T FORGET THIS!
return 0;
}
答案 1 :(得分:0)
听起来像是boost :: any有点像你在想什么。不需要奇怪的继承层次结构,它可以自己存储任意类型(有某些限制)。
现在我关心的是你打算如何重新获得价值?您的代码如何确定该单元格是否包含int,std :: string或之前从未听说过的其他用户定义类型,而不是尝试将any_cast转换为某些类型列表(如果类型未列出...)?