2015-03-27 2 views
0

Один класс возвращает '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; 
} 

Это довольно сложно иметь дело с «недействительным *». Существуют ли какие-либо другие идеи для реализации чего-то простого (например, в первом примере кода)? Спасибо.

+1

Вы возвращаете указатели на локальные переменные. Никогда не делай этого :-). – AlexD

+0

'virtual void * GimeMeTheValue (void) {};' * does not * puke предупреждение компилятора о том, чтобы не возвращать значение? Это * кажется * достойным кандидатом для типа * variant *. Как написано, это вызывает неопределенное поведение в нескольких местах – WhozCraig

+0

AlexD, конечно!) – Pleeea

ответ

1

Нет базового класса Interface, который мог бы знать, какой отдельный тип данных хочет вернуть каждый потомок. Использование разных типов возвращаемых целей приводит к поражению цели полиморфизма. Таким образом, единственный способ, которым я могу это сделать, - это вернуть тип объекта, который знает, какое значение он имеет, а затем сделать объект объективным.

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

>> Использование разных типов возвращаемых целей приводит к поражению цели полиморфизма. << Я думаю, что это основная проблема в моей логике, спасибо – Pleeea

+0

@Pleeea: Да. Вы хотите использовать объект с помощью указателя базового класса, не заботясь о том, что такое производный класс, только то, что все производные классы реализуют согласованный интерфейс. В этом и заключается суть полиморфизма. У виртуальной функции не может быть разных типов возврата. Он может возвращать только один отдельный тип, к которому должны относиться все производные классы. Таким образом, чтобы производные классы возвращали разные типы, вам нужен отдельный тип возвращаемого значения, который может корректировать его поведение во время выполнения, что и делает вариант. –

Смежные вопросы