从基类指针集合调用非虚成员函数
Call a non-virtual member function from a collection of base-class pointers?
我有一个类D
,我想有类A,B,C
继承。但是,我想声明为pure virtual
的函数是模板化的。
不幸的是,用visual studio的话来说:
member function templates cannot be virtual
类A,B,C
具有以完全相同的方式调用的成员操作符,尽管可能返回不同的值(即double
或unsigned int
)。但我很高兴能让它只工作double
):
template<typename T>
double operator()(T&, unsigned int b){/*code*/};
我怎么能正确地创建类A,B,C
的多态集合(类似于std::vector<D*>
,将工作,如果我不想要成员函数模板),我想做什么?
一个我希望能够做到的例子:
std::default_random_engine rng((unsigned int) std::time(0));
std::vector<D*> v;
v.push_back(new A(0.3));
v.push_back(new B(1.0,3.2));
v.push_back(new C);
for(auto x : v){
for(auto y : x->operator()(rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
我不完全确定您想要做什么,但是如果您将模板定义移动到类而不是方法中,那么一切都很好。这样能达到你的目的吗?
template<typename T>
class A
{
public :
virtual double operator() (T& t, unsigned int b) = 0;
};
template<typename T>
class B : public A<T>
{
public:
virtual double operator() (T& t, unsigned int b)
{
// code
}
};
编辑:或者,假设您不想在类级别上使用模板,那么将随机计算从多态方法中移出,然后使用简单的多态方法来处理实际的困难部分如何?这假设您只想生成一个随机数,如果您想要更多,您总是可以创建一个随机数向量,其大小在构造中确定。无论如何,下面的代码演示了我所说的:
class D
{
public :
template<typename T>
double operator() (T& t, unsigned int b)
{
double calc_rand = t();
return DoStuff(calc_rand, b);
}
protected :
virtual double DoStuff(double rnd_value, unsigned int b) = 0;
};
class A : public D
{
protected :
virtual double DoStuff(double rnd_value, unsigned int b)
{
return rnd_value * b;
}
};
int main(void)
{
std::random_device rd;
A a;
std::cout << a(rd, 5) << std::endl;
}
这里很可能需要使用委托。如果所有的类都有相同的名称和参数,就像这样简单:
template <typename T>
class baseWrapper{
double method(T& a, unsigned int b) = 0;
};
template <typename T, typename myClass>
class wrapper: public baseWrapper<T>{
myClass &instance;
double method(T& a, unsigned int b){
return instance.method<T>(a,b);
};
wrapper(myClass &instance){this->instance = instance;};
};
然后你可以创建一个委托集合:
std::vector<baseWrapper<int>*> vec;
A myObject1, B myObject2;
wrapper<int,A> wrapper1(myObject1);
wrapper<int,B> wrapper2(myObject2);
vec.push_back(&wrapper1);
vec.push_back(&wrapper2);
如果函数的命名不同,则需要传递一个函数指针作为附加参数,或者使用SFINAE进行测试。
也许可以为成员函数的模板形参实现类型擦除。使用你的RNG示例:
class RandUIntIfc {
public:
virtual ~RandUIntIfc() = 0;
virtual unsigned int min() const = 0;
virtual unsigned int max() const = 0;
virtual unsigned int operator()() = 0;
};
class RandUInt {
public:
template <typename RNG>
explicit RandUInt(RNG& rng);
unsigned int min() const;
unsigned int max() const;
unsigned int operator()();
private:
std::shared_ptr<RandUIntIfc> impl_;
template <typename RNG>
class Impl : public RandUIntIfc {
public:
explicit Impl(RNG& rng);
virtual unsigned int min() const;
virtual unsigned int max() const;
virtual unsigned int operator()();
private:
RNG& ref_;
};
};
我希望所有实际的成员定义都是显而易见的。只剩下D
和使用它的代码的更改:
class D {
public:
virtual ~D() = 0;
virtual double operator()(RandUInt rng, unsigned int b) = 0;
};
std::default_random_engine rng((unsigned int) std::time(0));
RandUInt typeless_rng(rng);
std::vector<D*> v;
// ...
for(auto x : v){
for(auto y : x->operator()(typeless_rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
你不应该使用模板函数,而应该通过虚函数将delegate传递给rng。你可以这样写:
class D
{
virtual double operator()(std::function<int()>, int)=0;
};
然后这样命名:
std::default_random_engine rng;
std::vector<D*> v;
...
for(auto x : v)
{
std::cout << x->operator(std::bind(rng), 5) << ',';
}
相关文章:
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 将公共但非静态的成员函数与ALGLIB集成
- 使用指向成员的指针将成员函数作为参数传递
- 将重载的成员函数传递给函数模板
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 如何在C++中使用非静态成员函数作为回调函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 关联容器的下界复杂性:成员函数与非成员函数
- 在 C++ 中用派生类型重写成员函数
- 链表的泛型函数remove()与成员函数remove)
- 如何将lambda作为模板类的成员函数参数
- constexpr构造函数需要常量成员函数时出现问题
- 将自由函数绑定为类成员函数
- 区分非成员函数和头文件中的成员函数
- 如何从子成员函数修改父公共成员变量
- 保留对其他类的成员函数的引用
- 在运算符重载定义中使用成员函数(const错误)
- 内联如何影响模块接口中的成员函数
- 将成员函数指针作为参数传递给模板方法