2012-05-30 65 views
2

我想在C++中定义一个基类,该类有纯虚方法由子类实现。C++:如何定义一个具有泛型返回类型的虚函数?

我想为基类中的基本类型定义setter和getter函数,但我希望派生类能够确定getter和setter的基本类型。比如我的基类是这样的:

class Value 
    { 
    public: 
     Value(); 
     template <class T>; 
     virtual T getValue() = 0; 
     virtual void setValue(T val) = 0; 
    } 

和我的孩子类将是这个样子:

class IntValue : public Value 
    { 
    public: 
     IntValue(); 
     template <class T> 
     T getValue() {return _val}; 
     void setValue(T val) {_val = val}; 
    private: 
     int _val; 
    } 

当然上面的代码不起作用。任何想法如何实现这一目标?提前致谢。

+1

你已经打了'virtual'墙... –

+1

如果类型的数量是有限的你可以使用boost的'variant'类型来实现有限的动态类型。 –

+1

@ edA-qamort-ora-y:对于不受限制的一组类型,您可以使用'boost :: any'完成相同的操作 - 但是您需要为间接级别付费。 –

回答

4

如果我理解正确你的问题,你重写代码

template <class T> 
class Value 
{ 
public: 
    Value(); 
    virtual T getValue() = 0; 
    virtual void setValue(T val) = 0; 
}; 


class IntValue : public Value<int> 
{ 
public: 
    IntValue(); 

    int getValue() {return _val;} 
    void setValue(int val) {_val = val;} 
private: 
    int _val; 
}; 

应该工作

+0

+1 - 这不能回答OP的问题,但它可能会达到与OP真正想要的类似的效果,因为它们命名了类和问题描述。 –

+2

在这种情况下,“IntValue”不是“Value”的子类。因此,“虚拟”关键字毫无意义。你将无法定义一个函数,该函数需要一个'Value *'并将'IntValue'传递给它。 –

+0

@Steven:确实;你甚至不能创建一个“Value”或“Value *”;它必须是某种类型的“价值”或“价值 *”。 –

3

什么你问的是不可能的。为了在vtbl(或编译器可能使用的任何类似结构)中生成正确的条目,编译器需要知道基类中特别需要哪些条目。你不能只在派生类中返回一个不同的类型,并期望基类以这种方式“知道”它;因为这需要修改基类中函数模板的定义。

可以如何使用类模板(而不是函数模板)做这种基类的修改的一个例子可以在J_D's answer可见,但仍然不符合您的问题说明确切地说,因为你不能创建一个Value并对其进行多态处理。

C++模板本质上是“花式裤子查找和替换”的类型 - 当编译器实例化函数模板时,它会生成一个普通函数,并替换类型名称。请注意,这与C#或Java的“泛型”完全不同,它们完全不同,并且依赖于运行时支持和一个间接层来实现类似的效果。 (请注意,虽然这个“查找和替换”尊重优先规则,但与C预处理宏不同:))

如果你真的想到它,这种模式没有任何意义。这在客户端的事情看起来会是什么样子?

class Value 
{ 
public: 
    Value(); 
    //Imagine if this were possible... 
    template <class T>; 
    virtual T getValue() = 0; 
    virtual void setValue(T val) = 0; 
} 

class IntValue : public Value 
{ 
public: 
    IntValue(); 
    int getValue() {return _val}; 
    void setValue(int val) {_val = val}; 
private: 
    int _val; 
} 

class FloatValue : public Value 
{ 
public: 
    FloatValue(); 
    float getValue() {return _val}; 
    void setValue(float val) {_val = val}; 
private: 
    float _val; 
} 

现在,你去使用这个类:

void example(Value * ptr) 
{ 
    //What could you possibly say the type of "bar" is? There's no type that works! 
    ???? bar = ptr->getValue(); 
    delete ptr; 
} 

int main() 
{ 
    example(new IntValue()); 
    example(new FloatValue()); 
} 

因此,即使这是允许的,就没有太大的意义。你总是不得不一直沮丧,这意味着virtual关键字无论如何都毫无意义。

+0

我希望更多的人真正理解模板的真正含义。模板是具有类型检查和其他幻想的宏。 –

1

扩大在什么@Billy奥尼尔说,大约一个类模板,这可能会满足您的需要:

template<typename Type> 
class Value 
{ 
public: 
    virtual Type getValue() = 0; 
}; 

class IntValue : public Value<int> 
{ 
public: 
    IntValue(int value) 
     : m_value(value) 
    { 
    } 

    int getValue() 
    { 
     return m_value; 
    } 

private: 
    int m_value; 
}; 
+1

这与J_D的解决方案有何不同? –

+1

这是不同的,我没有看到他的解决方案(奇怪的是,因为我看到了你的解决方案)。然而,我确实赞扬了他的解决方案。 – SirPentor

相关问题