我有两节课:
struct A {
template <typename T>
void print(T& t){
// do sth specific for A
}
};
struct B : A {
template <typename T>
void print(T& t){
// do sth specific for B
}
};
在这种情况下,由于没有虚拟模板,因此无法编译具有虚函数(A和B都继承自)的更一般的Base类。当我试图将所有A或B对象委托给同一个“界面”时,是否有人有想法解决这个问题?先感谢您。
此致 君
答案 0 :(得分:3)
您可以考虑使用CRTP。
template<typename Derived>
struct Base {
template <typename T>
void print(T& t){
static_cast<Derived*>(this)->print(t);
}
};
struct A : Base<A> {
// template print
};
struct B : Base<B> {
// template print
};
示例用法:
template<typename T, typename ARG>
void foo (Base<T>* p, ARG &a)
{
p->print(a);
}
此方法将被称为
foo(pA, i); // pA is A*, i is int
foo(pB, d); // pB is B*, d is double
答案 1 :(得分:2)
使用代理类获取B的方法
class A {
public:
friend class CProxyB;
virtual CProxyB* GetCProxyB() = 0;
};
class B;
class CProxyB
{
public:
CProxyB(B* b){mb = b;}
template <typename T>
void printB(T& t)
{
mb->print(t);
}
B* mb;
};
class B:public A {
public:
virtual CProxyB* GetCProxyB(){return new CProxyB(this);};
template <typename T>
void print(T& t){
printf("OK!!!!!\n");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* a = new B;
CProxyB* pb = a->GetCProxyB();
int t = 0;
pb->printB(t);
return 0;
}
答案 2 :(得分:0)
两个选项:
选项一:虚拟化方法,如果用户没有提供实现,则使用Base类。
template <typename T>
struct A {
virtual void print(T& t);
};
template <typename T>
void A::print(T& t) {
// do sth specific for A
}
template <typename T>
struct B : A {
virtual void print(T& t);
};
void B::print(T& t) {
// do sth specific for B
}
选项二:抽象方法,如果用户不提供实现,代码将无法编译。
template <typename T>
struct A {
virtual void print(T& t)=0;
};
template <typename T>
struct B : A {
virtual void print(T& t){
// do sth specific for B
}
};
template <typename T>
void B::print(T& t){
// do sth specific for B
}
除了上面提到的,如果你不使它们成为虚拟,Derived类将使用Shadow the Base类方法,这肯定不是你想要的。因此,不可能。
答案 3 :(得分:0)
我的问题是如何使用指向不同A或B对象的单个指针。
您可以在没有虚拟功能的情况下执行此操作。但你真正要做的就是编写一个V表和虚函数的实现。
如果我要手动实现虚函数,我会将它全部基于Boost.Variant对象。该变体将有效地保存每个类的成员数据。要调用函数,请使用变体访问者函子。每个“虚函数”都有自己的访问者函子,对于变体中的每个可能的类型都会有不同的operator()重载。
所以你可能有这个:
typedef boost::variant<StructA, StructB, StructC> VirtualClass;
您可以在变体中存储这些对象中的任何一个。您可以在对象上调用“虚函数”,如下所示:
VirtualClass someObject(StructA());
boost::apply_visitor(FunctorA(), someObject);
类FunctorA是您的虚函数实现。这是一个访客,定义如下:
class FunctorA : public boost::static_visitor<>
{
void operator()(StructA &arg){
//Do something for StructA
}
void operator()(StructB &arg){
//Do something for StructB
}
void operator()(StructC &arg){
//Do something for StructC
}
}
访问者可以拥有由apply_visitor
返回的返回值。他们可以通过将参数存储为访问者类的成员来获取参数。等等。
最重要的是,如果您更改了变体类型,要添加新的“派生类”,您将会遇到任何没有新类型重载的仿函数的编译器错误。
但说实话,你应该只使用虚拟功能。
答案 4 :(得分:0)
通过使用CRTP(Curiously recurring template pattern),您可以在没有虚拟的情况下实现静态polymorphsim。
#include <iostream>
using namespace std;
#define MSG(msg) cout << msg << endl;
template<class Derived>
class Base{
public:
void print()
{
static_cast<Derived*>(this)->print();
}
};
class Derived1 : public Base<Derived1>
{
public:
void print()
{
MSG("Derived 1::print");
}
};
class Derived2 : public Base<Derived2>
{
public:
void print()
{
MSG("Derived 2::print");
}
};
template<class T>
void callme(Base<T>& p)
{
p.print();
}
int main()
{
Base<Derived1> p1;
Base<Derived2> p2;
callme(p1);
callme(p2);
system("pause");
return 0;
}
//Result :
//Derived 1::print
//Derived 2::print