Return 接口中虚函数的值

Return value of virtual functions in interface

一个classreturns'int',另一个returns'double'。两个 class 的接口中方法 'GiveMeTheValue' 的签名是什么。 我想编译以下代码:

class Interface
{
    public:
        virtual arbitrary_type GimeMeTheValue(void) {}; 
};

class TakeInt : public Interface
{
    public:
        arbitrary_type GimeMeTheValue(void) {
            return 10;
        }
};

class TakeDouble : public Interface
{
    public:
        arbitrary_type GimeMeTheValue(void) { 
            return 3.14;
        }
};

int main()
{
    Interface * obj;

    obj = new TakeInt(); 
    cout << obj -> GimeMeTheValue() << endl; // It's 10, thank you

    obj = new TakeDouble();
    cout << obj -> GimeMeTheValue() << endl; // Oh it's 3.14, I love you c++
}

当然没有"arbitary_type"。 这有效...

class Interface
{
    public:
        virtual void * GimeMeTheValue(void) {}; 
};

class TakeInt : public Interface
{
    public:
        void * GimeMeTheValue(void) {
            int value = 10;
            int * ptr = &value;
            return ptr; 
        }
};

class TakeDouble : public Interface
{
    public:
        void * GimeMeTheValue(void) { 
            double value = 3.14;
            double * ptr = &value;
            return ptr; 
        }
};

int main()
{
    Interface * obj;

    obj = new TakeInt();
    cout << *( (int *) (obj -> GimeMeTheValue()) ) << endl;

    obj = new TakeDouble();
    cout << *( (double *) (obj -> GimeMeTheValue()) ) << endl;
}

处理起来比较复杂"void *"。有没有其他想法来实现一些简单的东西(比如第一个代码示例)?谢谢。

基础 class Interface 不可能知道每个后代想要什么不同的数据类型 return。使用不同的 return 类型违背了多态性的目的。所以我能想到的唯一方法是让 GiveMeTheValue() return 一个知道它拥有什么样的值的对象类型,然后使该对象可流化。

enum VariantType {varNull, varInt, varDouble};

struct Variant
{
    VariantType Type;
    union {
        int intValue;
        double dblValue;
    };

    Variant() : Type(varNull) {}
    Variant(int value) : Type(varInt), intValue(value) {}
    Variant(double value) : Type(varDouble), dblValue(value) {}

    void writeTo(std::ostream &strm)
    {
        switch (Type)
        {
            case varNull:   strm << "(null)"; break;
            case varInt:    strm << intValue; break;
            case varDouble: strm << dblValue; break; 
        }
    }
};

class Interface
{
public:
    virtual ~Interface() {}
    virtual Variant GimeMeTheValue(void) = 0; 
};

class TakeInt : public Interface
{
public:
    Variant GimeMeTheValue(void)
    {
        return Variant(10);
    }
};

class TakeDouble : public Interface
{
public:
    Variant GimeMeTheValue(void)
    { 
        return Variant(3.14);
    }
};

std::ostream& operator<<(std::ostream &strm, const Variant &v)
{
    v.writeTo(strm);
    return strm;
}

int main()
{
    Interface * obj;

    obj = new TakeInt(); 
    cout << obj->GimeMeTheValue() << endl; // It's 10, thank you
    delete obj;

    obj = new TakeDouble();
    cout << obj->GimeMeTheValue() << endl; // Oh it's 3.14, I love you c++
    delete obj;
}