Подтвердить что ты не робот

Приведение С++ в производный класс

Как я могу передать производный класс? Приведенные ниже подходы дают следующую ошибку:

Невозможно преобразовать из BaseType в DerivedType. Конструктор не может тип источника или разрешение перегрузки конструктора были неоднозначными.

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
4b9b3361

Ответ 1

Подумайте вот так:

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.

Теперь оглядываясь на ваше первое утверждение:

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

Вам очень редко приходится использовать динамический ролик.
Вот почему у нас есть виртуальные методы:

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

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

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

Единственная причина, по которой я могу думать, это сохранить ваш объект в контейнере базового класса:

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.

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

barnYard[1]->DoNoiseMake();

Ответ 2

dynamic_cast должен быть тем, что вы ищете.

EDIT:

DerivedType m_derivedType = m_baseType; // gives same error

Вышеупомянутое, похоже, пытается вызвать оператор присваивания, который, вероятно, не определен в типе DerivedType и принимает тип BaseType.

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

Вы находитесь на правильном пути здесь, но использование dynamic_cast будет пытаться безопасно применять к поставляемому типу, и если он не выполняется, возвращается NULL.

Идти в память здесь, попробуйте это (но заметьте, что cast вернет NULL при выводе из базового типа в производный тип):

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

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

Надеюсь, это поможет!

Ответ 3

Вы не можете применить базовый объект к производному типу - он не относится к этому типу.

Если у вас есть указатель базового типа на производный объект, вы можете использовать этот указатель с помощью dynamic_cast. Например:

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

Ответ 4

Прежде всего - предпосылкой для понижающего является то, что объект, который вы выполняете, относится к типу, на который вы производите. Casting with dynamic_cast проверяет это условие во время выполнения (при условии, что у кастового объекта есть некоторые виртуальные функции) и бросает bad_cast или возвращает NULL указатель на сбой. Сроки компиляции не будут проверять что-либо и будут вести поведение tu undefined, если это условие не выполняется.
Теперь проанализируем ваш код:

DerivedType m_derivedType = m_baseType;

Здесь нет кастинга. Вы создаете новый объект типа DerivedType и пытаетесь инициализировать его значением переменной m_baseType.

Следующая строка не намного лучше:

DerivedType m_derivedType = (DerivedType)m_baseType;

Здесь вы создаете временный тип DerivedType, инициализированный значением m_baseType.

Последняя строка

DerivedType * m_derivedType = (DerivedType*) & m_baseType;

должен компилироваться при условии, что BaseType является прямым или косвенным общедоступным базовым классом DerivedType. В любом случае, у него есть два недостатка:

  • Вы используете устаревший стиль C-стиля. Правильный способ для таких отливок - static_cast<DerivedType *>(&m_baseType)
  • Фактический тип литого объекта не принадлежит DerivedType (поскольку он был определен как BaseType m_baseType;, поэтому любое использование указателя m_derivedType приведет к поведению undefined.