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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:53:24  来源:igfitidea点击:

C++ cast to derived class

c++inheritance

提问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_castor return NULLpointer 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 DerivedTypeand 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 DerivedTypetype initialized with m_baseTypevalue.

在这里,您正在创建一个DerivedTypem_baseType值初始化的临时类型。

The last line

最后一行

DerivedType * m_derivedType = (DerivedType*) & m_baseType;

should compile provided that BaseTypeis a direct or indirect public base class of DerivedType. It has two flaws anyway:

应该编译,前提是它BaseTypeDerivedType. 无论如何,它有两个缺陷:

  1. You use deprecated C-style cast. The proper way for such casts is
    static_cast<DerivedType *>(&m_baseType)
  2. The actual type of casted object is not of DerivedType (as it was defined as BaseType m_baseType;so any use of m_derivedTypepointer will result in undefined behaviour.
  1. 您使用已弃用的 C 样式转换。此类演员的正确方法是
    static_cast<DerivedType *>(&m_baseType)
  2. 强制转换对象的实际类型不是 DerivedType(因为它被定义为BaseType m_baseType;任何m_derivedType指针的使用都将导致未定义的行为。