这段代码:
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>
呢?这似乎是一个问题,因为浮点数没有%=
运算符。但实际上并非如此,因为我永远不会在operator %=
上调用Primitive<float>
。这是模板的故意功能之一。
如果由于某种原因,我将
operator %=
定义为虚拟的。或者,如果我要从dll中预导出Primitive<float>
以避免链接错误,即使我从未在operator %=
上调用Primitive<float>
,编译器也会提示。如果只是在operator %=
的vtable中为Primitive<float>
填充一个虚拟值(会引发异常?),一切都会很好。 最佳答案
将虚函数放入可选的基类中...
struct Jumper
{
virtual void Jump =0;
};
struct Crawler
{
virtual void Crawl() =0;
};
struct JumperCrawler:
public Jumper,
public Crawler
{
};
template<typename T, typename Methods>
class ICanBoostJumpingAndCrawling :
public Methods
{
T t;
};
现在,您可以将ICanBoostJumpingAndCrawling与作为Methods模板参数提供的Jumper,Crawler或JumperCrawler一起使用;意识到需要从中派生它,以便可以在子类中实现Jumping和/或Crawling。
仅供引用,这使“ICanBoostJumpingAndCrawling”这个名称完全具有误导性,因为它可能会或可能不会这样做;这意味着应将其重命名为“Booster”之类的名称。
关于c++ - 模板类+虚函数=必须实现?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1489744/