2011-01-28 19 views

Respuesta

5

Porque, ¿cómo volvería el código que usa el valor de retorno a todo tipo de tipos no relacionados? ej .:

class A 
{ 
public: 
    virtual float func(); 
}; 

class B: public A 
{ 
public: 
    virtual char *func(); 
}; 

A *p = (some_condition) ? new A() : new B(); 
p->func(); // Oh no! What is the type? 
+0

Sí, tipo no relacionado = malo. ¿Qué pasa con otros tipos relacionados? – curiousguy

13

Debido a las tonterías que se derivarían:

struct foo 
{ 
    virtual int get() const { return 0; } 
}; 

struct bar : foo 
{ 
    std::string get() const { return "this certainly isn't an int"; } 
}; 

int main() 
{ 
    bar b; 
    foo* f = &b; 

    int result = f->get(); // int, right? ...right? 
} 

No es conveniente contar con un retorno clase derivada algo totalmente sin relación.

+0

Discusión [se trasladó al chat.] (Http://chat.stackoverflow.com/rooms/15288/discussion-between-gmannickg-and-curiousguy) – GManNickG

+0

Conclusión del chat: ** GManNickG admite que la regla actual de C++ que solo permite que los punteros (o referencias) se puedan relajar. ** – curiousguy

+0

No es un "admitir", nunca lo negé en primer lugar ... – GManNickG

3

Según C++ estándar:

El tipo de retorno de una función primordial será, o bien idéntica al tipo de retorno de la anulado ción fun- o covariante con las clases de las funciones. Si una función D :: f anula una función B :: f, los tipos de retorno de las funciones son covariantes si cumplen los siguientes criterios:

1) ambos son punteros a clases o referencias a clases

2) la clase en el tipo de devolución de B :: f es la misma clase que la clase en el tipo de devolución de D :: f, o es una clase base directa o indirecta no ambigua y accesible de la clase tipo de devolución de D :: f

3) ambos punteros o referencia tienen la misma calificación de cv y el tipo de clase en el tipo de devolución de D :: f tiene la misma calificación cv o menos cv-qualification que el tipo de clase en el tipo de devolución de B :: f.

+1

La pregunta ya supone la restricción, pregunta por qué existe esta restricción. – GManNickG

1

La respuesta es muy similar a la dada por "Why can't I assign a vector<Apple*> to a vector<Fruit*>?" el FAQ de Bjarne Stroustrup.

La capacidad de modificar el tipo de devolución daría lugar a un agujero en el tipo de seguridad del lenguaje (ver la respuesta de @GManNickG para un ejemplo específico) cuando se trata de tipos polimórficos.

Hay una situación bastante común cuando afectar el tipo de retorno sería ideal: al devolver un puntero polimórfico de un método virtual de un tipo base. Por ejemplo,

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

class Child : public Base { 
public: 
    Base* parent() override 
    { 
     return parent_; 
    } 
private: 
    Parent* parent_; // Assume `Parent` type exists. 
}; 

Aquí se pierde la información de tipo que sabe de Child es parent_ miembro. Esto conduce a una gran cantidad de fundición, a pesar de que el tipo estaba en un punto bien definido. Podemos resolver esto utilizando el lenguaje Curiously Recurring Template Parameter (CRTP),

template<class ParentType> 
class Base { 
public: 
    virtual ParentType* parent() 
    { 
     return parent_; 
    } 

private: 
    ParentType* parent_; 

}; 

class Child : public Base<Parent> { 
}; 
+0

"_La respuesta es muy similar a la de" ¿Por qué no puedo asignar un vector a un vector ? "En las preguntas frecuentes de Bjarne Stroustrup._" No es similar de ninguna manera. "_ La capacidad de modificar el tipo de devolución daría lugar a un agujero en el tipo de seguridad del lenguaje_" La capacidad de modificar el tipo de devolución ** sin ninguna restricción ** obviamente no es segura. Eso no responde a la pregunta original "¿por qué tenemos ** esta restricción **?" no "¿por qué tenemos alguna restricción?" – curiousguy

Cuestiones relacionadas