1

Реферирование этот вопрос: C++ virtual function return typeC++ Виртуальный метод возвращать различные производные типы

Рассмотрим следующий набор объектов.

class ReturnTypeBase 
{ 
}; 

class ReturnTypeDerived1 : public ReturnTypeBase 
{ 
public: 
    int x; 
}; 

class ReturnTypeDerived2 : public ReturnTypeBase 
{ 
public: 
    float y; 
}; 

class Base 
{ 
public: 
    virtual ReturnTypeBase* Get() = 0; 
}; 

class Derived1: public Base 
{ 
public: 
    virtual ReturnTypeDerived1* Get() 
    { 
     return new ReturnTypeDerived1(); 
    } 
}; 

class Derived2: public Base 
{ 
public: 
    virtual ReturnTypeDerived2* Get() 
    { 
     return new ReturnTypeDerived2(); 
    } 
}; 

Могут ли эти объекты использоваться следующим образом?

Base* objects[2]; 

objects[0] = new Derived1(); 

objects[1] = new Derived2(); 

ReturnTypeDerived1* one = objects[0]->Get(); 

ReturnTypeDerived2* two = objects[1]->Get(); 

Я предполагаю, так как возвращаемые типы ковариантны (?), Что множество объектов выше правовой C++. Будет ли вызываться соответствующий метод Get()? Могут ли указатели one/two присваивать возвращаемое значение метода Get() без кастования?

+0

Вы имели в виду 'ReturnTypeDerived1 * one = objects [0] -> Get();'? – wally

+0

@flatmouse Да, почти получил изменение в.: D –

+0

У вас есть случай использования? – curiousguy

ответ

4

Код не компилируется в письменном виде. Поскольку objects[0] имеет статический тип Base*, вызов функции Get приводит к указанию со статическим типом ReturnTypeBase*. Так как это переопределенная виртуальная функция, функция производного класса Get будет вызываться так, как вы ожидали бы, и возвращаемый указатель фактически указал бы на объект ReturnTypeDerived1, но компилятор не может это доказать. Вы должны были бы бросок:

auto one = static_cast<ReturnTypeDerived1*>(objects[0]->Get()); 
auto two = static_cast<ReturnTypeDerived2*>(objects[1]->Get()); 

Если вы ReturnTypeBase полиморфный тип, вы можете использовать dynamic_cast здесь вместо того, чтобы избежать неопределенное поведение, если вам случится быть неправильно о динамическом типе.

+0

Здесь нет ошибки? Должна ли 'dynamic_cast' быть' static_cast'? – wally

+0

@flatmouse Вы также можете использовать 'static_cast', но тогда у вас нет способа сказать, были ли вы ошибаетесь в отношении фактического типа. – Brian

+1

'dynamic_cast' не будет работать, потому что 'ReturnTypeBase' не является полиморфным типом. –

0

Как написано, вы получите ошибки компилятора в вызове .Get(). Если вы хотите, чтобы избежать этого, сделать задание на базовый класс ..

ReturnTypeBase * one = objects[0].Get(); 
ReturnTypeBase * two = objects[1].Get(); 

Пока доступ «один» и «два» через абстрактные методы, определенные в базовом классе, (например, а «ToString() '), у вас не будет проблем с внутренними данными.

Если вы намерены обрабатывать данные одинаково во всех экземплярах базового класса, вы можете захотеть вместо этого использовать класс шаблона.

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