我有一个班级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;
}
答案 0 :(得分:2)
我不完全确定你想要做什么,但是如果你将模板定义移到类而不是方法上,一切都很愉快。这样做你想要的吗?
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
}
};
编辑:
或者,鉴于您不希望在类级别使用模板,那么将随机计算从多态方法中移出,然后对实际的硬件部分使用简单的plymorphic方法。这假设您只想生成一个随机数,如果您想要更多,您可以随时创建一个随机数的向量,其大小在构造中确定。无论如何,下面的代码演示了我在说什么:
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;
}
答案 1 :(得分:0)
你很可能需要在这里使用delegates。如果所有类都具有相同的名称和参数,那么就像执行操作一样简单:
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进行测试。
答案 2 :(得分:0)
您不应该使用模板函数,只需通过虚函数将委托传递给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) << ',';
}
答案 3 :(得分:0)
也许您可以为成员函数的模板参数实现类型擦除。按照您的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;
}