C++:如何定义具有泛型返回类型的虚函数?

vddsk6oq  于 2023-02-06  发布在  其他
关注(0)|答案(3)|浏览(153)

我试图用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;
}

当然上面的代码不起作用。有什么想法如何实现这一点?提前感谢。

wnavrhmk

wnavrhmk1#

如果我没理解错的话,将代码重写为

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;
};

应该可以

lg40wkob

lg40wkob2#

你所要求的是不可能的。为了在vtbl中生成正确的条目(或者编译器可能使用的任何类似结构),编译器需要知道基类中具体需要哪些条目。你不能只是在派生类中返回一个不同的类型,并期望基类以那种方式“知道”它;因为这将需要修改基类中的函数模板的定义。
J_D's answer中可以看到一个如何使用 class template(而不是 function template)对基类进行这种修改的示例,但这仍然与您的问题描述不完全匹配,因为您无法创建一个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关键字将毫无意义。

zbsbpyhn

zbsbpyhn3#

扩展@比利ONeal关于类模板的说法,这可能对您的目的有用:

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;
};

相关问题