接口中虚函数的返回值

时间:2015-03-27 23:59:08

标签: c++ interface virtual void void-pointers

一个类返回'int',其他返回'double'。在两个类的接口中,方法'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 *”相当复杂。有没有其他想法来实现简单的东西(比如在第一个代码示例中)?谢谢。

1 个答案:

答案 0 :(得分:1)

基类Interface无法知道每个后代想要返回的不同数据类型。使用不同的返回类型会破坏多态性的目的。因此,我认为这样做的唯一方法是让GiveMeTheValue()返回一个对象类型,该对象类型知道它拥有什么样的值,然后使该对象可以流化。

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