我听说c++的类成员函数模板不能是虚的。这是真的吗?
如果它们可以是虚拟的,那么有什么场景可以使用这样的函数呢?
我听说c++的类成员函数模板不能是虚的。这是真的吗?
如果它们可以是虚拟的,那么有什么场景可以使用这样的函数呢?
当前回答
不可以,模板成员函数不能为虚函数。
其他回答
回答问题的第二部分:
如果它们可以是虚拟的,那么有什么场景可以使用这样的函数呢?
这并不是一件不合理的事情。例如,Java(每个方法都是虚的)使用泛型方法没有问题。
c++中需要虚函数模板的一个例子是接受泛型迭代器的成员函数。或接受泛型函数对象的成员函数。
这个问题的解决方案是使用boost::any_range和boost::function的类型擦除,这将允许您接受泛型迭代器或函子,而不需要使您的函数成为模板。
不可以,模板成员函数不能为虚函数。
在虚函数的情况下如何调用正确的函数?
虚表将包含类的每个虚函数的条目,在运行时,它将选择特定函数的地址,并调用各自的函数。
如何正确的函数必须被调用在虚拟情况下连同函数模板?
在函数模板的情况下,用户可以使用任何类型调用该函数。这里相同的函数根据类型有几个版本。现在,在这种情况下,对于同一个函数,由于版本不同,必须维护vtable中的许多项。
模板都是关于编译器在编译时生成代码的。虚函数都是关于运行时系统确定在运行时调用哪个函数。
一旦运行时系统发现它需要调用模板化的虚函数,编译就完成了,编译器就不能再生成相应的实例了。因此,不能使用虚拟成员函数模板。
然而,结合多态性和模板产生了一些强大而有趣的技术,特别是所谓的类型擦除。
如果预先知道模板方法的类型集,则'虚拟模板方法'有一个变通方法。
为了说明这个想法,在下面的例子中只使用了两种类型(int和double)。
在那里,一个“虚拟”模板方法(Base:: method)调用相应的虚拟方法(Base:: VMethod之一),后者反过来调用模板方法实现(Impl::TMethod)。
只需要在派生实现(AImpl, BImpl)中实现模板方法TMethod,并使用derived <*Impl>。
class Base
{
public:
virtual ~Base()
{
}
template <typename T>
T Method(T t)
{
return VMethod(t);
}
private:
virtual int VMethod(int t) = 0;
virtual double VMethod(double t) = 0;
};
template <class Impl>
class Derived : public Impl
{
public:
template <class... TArgs>
Derived(TArgs&&... args)
: Impl(std::forward<TArgs>(args)...)
{
}
private:
int VMethod(int t) final
{
return Impl::TMethod(t);
}
double VMethod(double t) final
{
return Impl::TMethod(t);
}
};
class AImpl : public Base
{
protected:
AImpl(int p)
: i(p)
{
}
template <typename T>
T TMethod(T t)
{
return t - i;
}
private:
int i;
};
using A = Derived<AImpl>;
class BImpl : public Base
{
protected:
BImpl(int p)
: i(p)
{
}
template <typename T>
T TMethod(T t)
{
return t + i;
}
private:
int i;
};
using B = Derived<BImpl>;
int main(int argc, const char* argv[])
{
A a(1);
B b(1);
Base* base = nullptr;
base = &a;
std::cout << base->Method(1) << std::endl;
std::cout << base->Method(2.0) << std::endl;
base = &b;
std::cout << base->Method(1) << std::endl;
std::cout << base->Method(2.0) << std::endl;
}
输出:
0
1
2
3
注: Base::Method对于实际代码来说实际上是多余的(VMethod可以被设为public并直接使用)。 我添加它,使它看起来像一个实际的“虚拟”模板方法。