resueltos resolucion que poo polimorfismo operador objeto ejercicios ejemplos codigo clases ambito c++ inheritance

resolucion - polimorfismo c++



Lanzamiento de C++ a la clase derivada (4)

¿Cómo puedo lanzar a una clase derivada? Los enfoques a continuación dan el siguiente error:

No se puede convertir de BaseType a DerivedType. Ningún constructor podría tomar el tipo de fuente, o la resolución de sobrecarga del constructor era ambigua.

BaseType m_baseType; DerivedType m_derivedType = m_baseType; // gives same error DerivedType m_derivedType = (DerivedType)m_baseType; // gives same error DerivedType * m_derivedType = (DerivedType*) & m_baseType; // gives same error


En primer lugar, el requisito previo para Downcast es que el objeto que estás lanzando sea del tipo al que estás lanzando. Casting con dynamic_cast verificará esta condición en tiempo de ejecución (siempre que el objeto casted tenga algunas funciones virtuales) y lanzará bad_cast o devolverá el puntero NULL en caso de falla. Los moldes de tiempo de compilación no verifican nada y solo generarán un comportamiento indefinido si este requisito previo no se cumple.
Ahora analizando tu código:

DerivedType m_derivedType = m_baseType;

Aquí no hay casting. Está creando un nuevo objeto de tipo DerivedType e intenta inicializarlo con el valor de la variable m_baseType.

La siguiente línea no es mucho mejor:

DerivedType m_derivedType = (DerivedType)m_baseType;

Aquí está creando un tipo DerivedType temporal inicializado con el valor de m_baseType .

La última línea

DerivedType * m_derivedType = (DerivedType*) & m_baseType;

debería compilarse siempre que BaseType sea ​​una clase base pública o indirecta de DerivedType . Tiene dos defectos de todos modos:

  1. Usas el estilo C obsoleto. La forma correcta para tales moldes es
    static_cast<DerivedType *>(&m_baseType)
  2. El tipo real de objeto emitido no es de DerivedType (como se definió como BaseType m_baseType; por lo que cualquier uso del puntero m_derivedType dará como resultado un comportamiento indefinido.

No puede convertir un objeto base en un tipo derivado; no es de ese tipo.

Si tiene un puntero de tipo base para un objeto derivado, entonces puede convertir ese puntero usando dynamic_cast. Por ejemplo:

DerivedType D; BaseType B; BaseType *B_ptr=&B BaseType *D_ptr=&D;// get a base pointer to derived type DerivedType *derived_ptr1=dynamic_cast<DerivedType*>(D_ptr);// works fine DerivedType *derived_ptr2=dynamic_cast<DerivedType*>(B_ptr);// returns NULL


Piensa así:

class Animal { /* Some virtual members */ }; class Dog: public Animal {}; class Cat: public Animal {}; Dog dog; Cat cat; Animal& AnimalRef1 = dog; // Notice no cast required. (Dogs and cats are animals). Animal& AnimalRef2 = cat; Animal* AnimalPtr1 = &dog; Animal* AnimlaPtr2 = &cat; Cat& catRef1 = dynamic_cast<Cat&>(AnimalRef1); // Throws an exception AnimalRef1 is a dog Cat* catPtr1 = dynamic_cast<Cat*>(AnimalPtr1); // Returns NULL AnimalPtr1 is a dog Cat& catRef2 = dynamic_cast<Cat&>(AnimalRef2); // Works Cat* catPtr2 = dynamic_cast<Cat*>(AnimalPtr2); // Works // This on the other hand makes no sense // An animal object is not a cat. Therefore it can not be treated like a Cat. Animal a; Cat& catRef1 = dynamic_cast<Cat&>(a); // Throws an exception Its not a CAT Cat* catPtr1 = dynamic_cast<Cat*>(&a); // Returns NULL Its not a CAT.

Ahora mirando hacia atrás en su primera declaración:

Animal animal = cat; // This works. But it slices the cat part out and just // assigns the animal part of the object. Cat bigCat = animal; // Makes no sense. // An animal is not a cat!!!!! Dog bigDog = bigCat; // A cat is not a dog !!!!

Raramente deberías necesitar usar un cast dinámico.
Es por eso que tenemos métodos virtuales:

void makeNoise(Animal& animal) { animal.DoNoiseMake(); } Dog dog; Cat cat; Duck duck; Chicken chicken; makeNoise(dog); makeNoise(cat); makeNoise(duck); makeNoise(chicken);

La única razón por la que puedo pensar es si almacenaste tu objeto en un contenedor de clase base:

std::vector<Animal*> barnYard; barnYard.push_back(&dog); barnYard.push_back(&cat); barnYard.push_back(&duck); barnYard.push_back(&chicken); Dog* dog = dynamic_cast<Dog*>(barnYard[1]); // Note: NULL as this was the cat.

Pero si necesita devolver objetos particulares a Perros, entonces hay un problema fundamental en su diseño. Debería acceder a las propiedades a través de los métodos virtuales.

barnYard[1]->DoNoiseMake();


dynamic_cast debería ser lo que estás buscando.

EDITAR:

DerivedType m_derivedType = m_baseType; // gives same error

Lo anterior parece estar intentando invocar al operador de asignación, que probablemente no está definido en el tipo DerivedType y que acepta un tipo de BaseType.

DerivedType * m_derivedType = (DerivedType*) & m_baseType; // gives same error

Está en el camino correcto aquí, pero el uso de dynamic_cast intentará transmitir de forma segura al tipo suministrado y, si falla, se devolverá un NULL.

Continuando con la memoria aquí, intente esto (pero tenga en cuenta que el molde arrojará NULL mientras está lanzando desde un tipo base a un tipo derivado):

DerivedType * m_derivedType = dynamic_cast<DerivedType*>(&m_baseType);

Si m_baseType era un puntero y apuntaba a un tipo de DerivedType, entonces el dynamic_cast debería funcionar.

¡Espero que esto ayude!