C++ cast to derived class

Jak mogę rzucić do klasy pochodnej? Wszystkie poniższe podejścia dają następujący błąd:

Nie można przekonwertować z BaseType na DerivedType. Żaden konstruktor nie wytrzymałby typ źródła lub rozdzielczość przeciążenia konstruktora była niejednoznaczna.

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
Author: gsamaras, 2011-03-15

4 answers

Myśl tak:

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.

Teraz patrząc wstecz na twoją pierwszą wypowiedź:

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 !!!!

Bardzo rzadko trzeba używać dynamicznej obsady.
Dlatego mamy metody wirtualne:

void makeNoise(Animal& animal)
{
     animal.DoNoiseMake();
}

Dog    dog;
Cat    cat;
Duck   duck;
Chicken chicken;

makeNoise(dog);
makeNoise(cat);
makeNoise(duck);
makeNoise(chicken);

Jedynym powodem, dla którego mogę myśleć jest to, że przechowujesz swój obiekt w kontenerze klasy bazowej:

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.

Ale jeśli musisz rzucić poszczególne przedmioty z powrotem do psów, to jest fundamentalny problem w Twoim projekcie. Powinieneś uzyskać dostęp do właściwości za pośrednictwem wirtualnego metody.

barnYard[1]->DoNoiseMake();
 112
Author: Martin York,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 18:46:31

Dynamic_cast powinien być tym, czego szukasz.

EDIT:

DerivedType m_derivedType = m_baseType; // gives same error

Powyższe wydaje się próbować wywołać operator przypisania, który prawdopodobnie nie jest zdefiniowany na typie DerivedType i akceptuje Typ typu BaseType.

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

Jesteś na właściwej ścieżce, ale użycie dynamic_cast spróbuje bezpiecznie rzucić do dostarczonego typu i jeśli się nie powiedzie, zostanie zwrócone NULL.

Idąc pamięcią tutaj, spróbuj tego (ale zauważ, że obsada zwróci NULL jako przerzucasz z typu bazowego na typ Pochodny):

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

Jeśli m_basetype był wskaźnikiem i faktycznie wskazywał na typ DerivedType, to dynamic_cast powinien działać.

Mam nadzieję, że to pomoże!
 7
Author: Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-15 14:48:02

Nie można przypisać obiektu bazowego do typu pochodnego - nie jest on tego typu.

Jeśli masz wskaźnik typu bazowego do obiektu pochodnego, możesz rzucić ten wskaźnik za pomocą dynamic_cast. Na przykład:

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
 5
Author: Michael Kohne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-15 14:52:09

Po pierwsze - warunkiem wstępnym do downcast jest to, że obiekt, który rzucasz, jest typu, do którego rzucasz. Rzutowanie za pomocą dynamic_cast sprawdzi ten warunek w trybie runtime (pod warunkiem, że obiekt casted posiada pewne funkcje wirtualne) i rzuci bad_cast lub zwróci NULL Wskaźnik po niepowodzeniu. Rzuty w czasie kompilacji niczego nie sprawdzają i po prostu prowadzą tu undefined behavior, jeśli ten warunek nie jest spełniony.
Teraz analizuję Twój kod:

DerivedType m_derivedType = m_baseType;

Tutaj nie ma castingu. Jesteś utworzenie nowego obiektu typu DerivedType i próba zainicjalizowania go wartością zmiennej m_baseType.

Następna linijka nie jest dużo lepsza:

DerivedType m_derivedType = (DerivedType)m_baseType;

Tutaj tworzysz tymczasowy typ DerivedType zainicjalizowany wartością m_baseType.

Ostatni wiersz

DerivedType * m_derivedType = (DerivedType*) & m_baseType;

Powinna kompilować pod warunkiem, że BaseType jest bezpośrednią lub pośrednią publiczną klasą bazową DerivedType. I tak ma dwie wady:

  1. używasz przestarzałej obsady w stylu C. Właściwy sposób na takie odlewy jest
    static_cast<DerivedType *>(&m_baseType)
  2. rzeczywisty typ odlewanego obiektu nie jest DerivedType (ponieważ został zdefiniowany jako BaseType m_baseType;, więc każde użycie wskaźnika m_derivedType spowoduje niezdefiniowane zachowanie.
 2
Author: Tadeusz Kopec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-15 15:40:17