简体   繁体   中英

C++: How to define a virtual function with generic return type?

I'm trying to define a base a class in C++ that has pure virtual methods to be implemented by children classes.

I would like to define setter and getter functions for basic types in the base class, but I would like the derived class to be able to determine the basic type of the getter and setter. For instance my base class would look like this:

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

and my child class would look something like this:

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

Of course the above code does not work. Any ideas on how to achieve this? Thanks in advance.

If I understood your problem correctly, rewriting your code to

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

should work

What you're asking for is not possible. In order to generate the right entries in the vtbl (or whatever similar structure the compiler might be using), the compiler needs to know what entries are going to be needed in the base class specifically. You can't just return a different type in a derived class and expect the base class to "know" about it in that way; as that would require a modification of the definition of the function template in the base class.

An example of how you might do that kind of modification of the base class using a class template (rather than a function template ) can be seen in J_D's answer , but that still doesn't match your problem description exactly, because you wouldn't be able to create a Value and treat it polymorphicly.

C++ templates are essentially "fancy-pants find and replace" with the type -- when the compiler instantiates the function template, it generates a plain function with the typenames replaced. Note that this is very different than C# or Java "generics", which are completely different and rely on runtime support and a layer of indirection to achieve a similar effect. (Note though that this "find and replace" respects precedence rules and such, unlike C preprocessor macros :) )

If you really think about it too, this pattern does not make sense. What would this really look like on the client side of things?

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

Now, you go to use this class:

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

As such, even if this were allowed, it wouldn't make much sense. You'd always have to downcast all the time, which would mean that the virtual keyword would be meaningless anyway.

Expanding on what @Billy ONeal said about a class template, this may work for your purposes:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM