首先,很抱歉标题混淆了。这是我的OOP设置。我有基类base,还有两个纯虚拟函数add和multi。然后我派生了类D1和D2,并实现了add和multi函数。我想要一个模板函数,它可以灵活地在D1 D2和调用add或multi函数之间切换。我在谷歌上搜索了一下,有人说我应该使用函数指针,但也有人说它不适用于纯虚拟函数。
class Base
{ double data; //data member
Base(double d):data(d){};
virtual double add() = 0;
virtual double multi() = 0;
}
class D1::public Base
{ D1(double d): Base(d) {}; //calling base class constructor
double add() {return data+1;} ;
double multi() {return data*2;} ;
}
class D2::public Base
{ D2(double d): Base(d) {}; //calling base class constructor
double add() {return data+3;} ;
double multi() {return data*4;} ;
}
//now I want to have a template function that give me flexibility to construct D1 or D2 and calling add or multi.
template <typename T, typename F>
void testFun(double num)
{ T tmp(num); //create object either D1 or D2;
cout << T->F() << endl; //calling either add or multi;
}
int main()
{ testFun<D1, D1.add()>(double x = 5);
//i know passing in D1.add() is wrong i don't know how to fix, hopefully you know what I am trying to achieve
return 0;}
任何帮助都将不胜感激。谢谢大家。
虚拟成员函数不会使指向成员函数的指针失效。如果被调用的对象是指向具有实际实现的对象的指针/引用,则可以调用指向纯虚拟函数的指针。
首先,您似乎被如何将指针传递给成员函数的语法弄糊涂了。
还要注意,这里甚至不会使用虚拟调度,因为所使用的对象类型在编译时是已知的。
template <typename T>
void testFun(double num, double (T::*fn)())
{
T tmp(num);
std::cout << (tmp.*fn)() << std::endl;
}
这里,fn
是指向T
的成员函数的指针,该成员函数不接受参数并返回double
值。你可以这样调用它:
testFun<D1>(5, &D1::add);
注意您给出的示例代码中的其他一些错误:
- 当应该使用
:
时,可以使用::
指定基类型。例如:class D1 : public Base
- 您使用
class
,但从不指定访问修饰符,这意味着所有成员都是隐式private
。为了演示的目的,将它们更改为struct
(默认为public
访问(可以修复此问题 - 类/结构定义后需要一个分号
下面是工作代码的演示。
为了完整起见,这里有一个演示,显示可以使用指向纯虚拟成员函数的指针来调用指向派生类型的引用/指针。必须通过引用Base
来调整代码以使用D1
或D2
对象,以便调度是动态的。这个例子看起来像:
template <typename T>
void testFun(double num, double (Base::*fn)())
{
T tmpConcrete(num);
Base & tmp = tmpConcrete;
std::cout << (tmp.*fn)() << std::endl;
}
int main() {
testFun<D1>(5, &Base::add);
}
(当然,在这里,当通用代码知道T
是什么时,使用指向Base
成员的指针有点傻,但它证明了这是可能的。(