C++ 转换为派生类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5313322/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ cast to derived class
提问by user346443
How can i cast to a derived class? The below approaches all give the following error:
如何转换为派生类?以下方法都给出了以下错误:
Cannot convert from BaseType to DerivedType. No constructor could take the source type, or constructor overload resolution was ambiguous.
无法从 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
回答by Martin York
Think like this:
像这样思考:
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.
Now looking back at your first statement:
现在回顾你的第一句话:
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 !!!!
You should very rarely ever need to use dynamic cast.
This is why we have virtual methods:
您应该很少需要使用动态转换。
这就是为什么我们有虚方法:
void makeNoise(Animal& animal)
{
animal.DoNoiseMake();
}
Dog dog;
Cat cat;
Duck duck;
Chicken chicken;
makeNoise(dog);
makeNoise(cat);
makeNoise(duck);
makeNoise(chicken);
The only reason I can think of is if you stored your object in a base class container:
我能想到的唯一原因是,如果您将对象存储在基类容器中:
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.
But if you need to cast particular objects back to Dogs then there is a fundamental problem in your design. You should be accessing properties via the virtual methods.
但是,如果您需要将特定对象转换回 Dogs,那么您的设计就存在一个基本问题。您应该通过虚拟方法访问属性。
barnYard[1]->DoNoiseMake();
回答by Michael
dynamic_cast should be what you are looking for.
dynamic_cast 应该是你正在寻找的。
EDIT:
编辑:
DerivedType m_derivedType = m_baseType; // gives same error
The above appears to be trying to invoke the assignment operator, which is probably not defined on type DerivedType and accepting a type of BaseType.
上面似乎试图调用赋值运算符,它可能未在类型 DerivedType 上定义并接受 BaseType 类型。
DerivedType * m_derivedType = (DerivedType*) & m_baseType; // gives same error
You are on the right path here but the usage of the dynamic_cast will attempt to safely cast to the supplied type and if it fails, a NULL will be returned.
您在这里走在正确的道路上,但 dynamic_cast 的使用将尝试安全地转换为提供的类型,如果失败,将返回 NULL。
Going on memory here, try this (but note the cast will return NULL as you are casting from a base type to a derived type):
在这里继续记忆,试试这个(但请注意,当您从基类型转换为派生类型时,转换将返回 NULL):
DerivedType * m_derivedType = dynamic_cast<DerivedType*>(&m_baseType);
If m_baseType was a pointer and actually pointed to a type of DerivedType, then the dynamic_cast should work.
如果 m_baseType 是一个指针并且实际上指向 DerivedType 的类型,那么 dynamic_cast 应该可以工作。
Hope this helps!
希望这可以帮助!
回答by Michael Kohne
You can't cast a base object to a derived type - it isn't of that type.
您不能将基础对象强制转换为派生类型 - 它不是那种类型。
If you have a base type pointer to a derived object, then you can cast that pointer around using dynamic_cast. For instance:
如果您有一个指向派生对象的基类型指针,那么您可以使用 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
回答by Tadeusz Kopec
First of all - prerequisite for downcast is that object you are casting is of the type you are casting to. Casting with dynamic_cast will check this condition in runtime (provided that casted object has some virtual functions) and throw bad_cast
or return NULL
pointer on failure. Compile-time casts will not check anything and will just lead tu undefined behaviour if this prerequisite does not hold.
Now analyzing your code:
首先 - 向下转换的先决条件是您正在转换的对象是您正在转换的类型。使用 dynamic_cast 进行强制转换将在运行时检查此条件(假设被强制转换的对象具有一些虚函数)并在失败时抛出bad_cast
或返回NULL
指针。如果此先决条件不成立,编译时强制转换不会检查任何内容,并且只会导致未定义的行为。
现在分析您的代码:
DerivedType m_derivedType = m_baseType;
Here there is no casting. You are creating a new object of type DerivedType
and try to initialize it with value of m_baseType variable.
这里没有铸造。您正在创建一个新的类型对象DerivedType
并尝试使用 m_baseType 变量的值对其进行初始化。
Next line is not much better:
下一行也好不到哪里去:
DerivedType m_derivedType = (DerivedType)m_baseType;
Here you are creating a temporary of DerivedType
type initialized with m_baseType
value.
在这里,您正在创建一个DerivedType
用m_baseType
值初始化的临时类型。
The last line
最后一行
DerivedType * m_derivedType = (DerivedType*) & m_baseType;
should compile provided that BaseType
is a direct or indirect public base class of DerivedType
. It has two flaws anyway:
应该编译,前提是它BaseType
是DerivedType
. 无论如何,它有两个缺陷:
- You use deprecated C-style cast. The proper way for such casts is
static_cast<DerivedType *>(&m_baseType)
- The actual type of casted object is not of DerivedType (as it was defined as
BaseType m_baseType;
so any use ofm_derivedType
pointer will result in undefined behaviour.
- 您使用已弃用的 C 样式转换。此类演员的正确方法是
static_cast<DerivedType *>(&m_baseType)
- 强制转换对象的实际类型不是 DerivedType(因为它被定义为
BaseType m_baseType;
任何m_derivedType
指针的使用都将导致未定义的行为。