【发布时间】:2010-12-02 03:55:02
【问题描述】:
这段代码:
template <typename T>
struct A
{
T t;
void DoSomething()
{
t.SomeFunction();
}
};
struct B
{
};
A<B> a;
只要我从不打电话给a.DoSomething(),就可以轻松编译,没有任何抱怨。
但是,如果我将DoSomething 定义为虚函数,我会收到一个编译错误,指出B 没有声明SomeFunction。我有点明白它为什么会发生(DoSomething 现在应该在 vtable 中有一个条目),但我不禁觉得它并不是真正的义务。再加上它很烂。
有什么办法可以克服吗?
编辑 2: 好的。我希望这一次有意义: 假设我正在做侵入式引用计数,所以所有实体都必须从基类 Object 继承。我怎样才能支持原始类型呢?我可以定义:
template <typename T>
class Primitive : public Object
{
T value;
public:
Primitive(const T &value=T());
operator T() const;
Primitive<T> &operator =(const T &value);
Primitive<T> &operator +=(const T &value);
Primitive<T> &operator %=(const T &value);
// And so on...
};
所以我可以使用Primitive<int>、Primitive<char>...
但是Primitive<float> 怎么样?这似乎是个问题,因为浮点数没有 %= 运算符。但实际上并非如此,因为我永远不会在Primitive<float> 上致电operator %=。
这是模板的深思熟虑的功能之一。
如果出于某种原因,我会将operator %= 定义为虚拟。或者,如果我要从 dll 中预导出 Primitive<float> 以避免链接错误,即使我从未在 Primitive<float> 上调用 operator %=,编译器也会抱怨。如果它只是在Primitive<float> 的vtable 中为operator %= 填写一个虚拟值(这会引发异常?),一切都会好起来的。
【问题讨论】:
-
如果你从不调用它,那么拥有这个函数有什么意义呢?如果它在您的类型 T 实例上调用 DoSomething,则类型 T 必须实现 DoSomething 方法。
-
重点是,如果合适的话,我可能会调用 DoSomething,也可能不会,这取决于上下文。 Ofcouse,如果我真的调用它,那么 T 必须实现任何必要的。这是模板更有用的属性之一。
-
这闻起来是糟糕的设计。 :|你到底想做什么?不是您的详细目标,而是您的任务目标。
-
您可以通过要求您的客户定义一个免费的 SomeFunction(T&); 来轻松解决它。您刚刚使用 SomeFunction(t); 调用的函数,该调用将选择任何可用的函数(作为后备,您自己的函数)。
-
@litb:如果我想使用原始类型的模板怎么办?我需要编译器在 vtable 中填写一个虚拟 thunk。
标签: c++ virtual-functions class-template