C ++转换为派生类
我怎样才能投射到派生类? 下面的方法都给出了以下错误:
无法从BaseType转换为DerivedType。 没有构造函数可以采取源types,或构造函数重载parsing是模糊的。
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
这样想:
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 !!!!
你应该很less需要使用dynamic投射。
这就是为什么我们有虚拟方法:
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.
但是如果你需要将特定的对象抛回到狗身上,那么在你的devise中就存在一个基本的问题。 您应该通过虚拟方法访问属性。
barnYard[1]->DoNoiseMake();
dynamic_cast应该是你在找什么。
编辑:
DerivedType m_derivedType = m_baseType; // gives same error
上述似乎试图调用赋值运算符,这可能没有定义typesDerivedType并接受一种BaseType。
DerivedType * m_derivedType = (DerivedType*) & m_baseType; // gives same error
你在这里是正确的path,但dynamic_cast的使用将尝试安全地转换为提供的types,如果失败,将返回一个NULL。
在这里回忆一下,试试这个(但是注意,当你从基types转换为派生types时,转换将返回NULL):
DerivedType * m_derivedType = dynamic_cast<DerivedType*>(&m_baseType);
如果m_baseType是一个指针,实际上指向一个DerivedTypetypes,那么dynamic_cast应该工作。
希望这可以帮助!
您不能将基础对象转换为派生types – 它不是这种types。
如果您有一个指向派生对象的基types指针,那么您可以使用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
首先 – 沮丧的先决条件是你正在施放的对象是你正在施放的types。 使用dynamic_cast进行投射将在运行时检查这个条件(假设铸造的对象有一些虚函数)并抛出bad_cast
或在失败时返回NULL
指针。 编译时间转换不会检查任何内容,只会导致tu未定义的行为,如果这个先决条件不成立。
现在分析你的代码:
DerivedType m_derivedType = m_baseType;
这里没有铸造。 您正在创buildDerivedType
types的新对象,并尝试使用m_baseTypevariables的值对其进行初始化。
下一行不太好:
DerivedType m_derivedType = (DerivedType)m_baseType;
在这里,您正在创build一个使用m_baseType
值初始化的DerivedType
types的临时值。
最后一行
DerivedType * m_derivedType = (DerivedType*) & m_baseType;
应该进行编译,前提是BaseType
是DerivedType
的直接或间接公共基类。 无论如何它有两个缺陷:
- 您使用不推荐的C风格转换。 这种演员的正确方法是
static_cast<DerivedType *>(&m_baseType)
- 铸造对象的实际types不是DerivedType(因为它被定义为
BaseType m_baseType;
所以任何对m_derivedType
指针的使用都会导致未定义的行为。