将 1st Derived Class 转换为 2nd Derived Class - 为什么它有效?
Casting 1st Derived Class to 2nd Derived Class - Why does it work?
我只是从基础 class 创建了两个派生 class。
然后创建一个派生class的对象并转换为基础class。
然后从基数 class 转换为派生的 class 第二个,
我希望它不会起作用,但它确实起作用了。
有人能解释一下下面的代码是如何工作的吗……我该如何防止这种情况发生……
PS:现在编辑程序使其更有意义。
这也是我想尽可能避免的情况:
class Animal
{
public:
Animal() { std::cout << "I am an animal\r\n"; };
virtual void makeSound() = 0;
~Animal() = default;
};
class Cat : public Animal
{
public:
Cat() { std::cout << "I am a Cat\r\n"; };
void makeSound() final { std::cout << "Meaow\r\n"; }
~Cat() = default;
};
class Dog : public Animal
{
public:
Dog() { std::cout << "I am a Dog\r\n"; };
void makeSound() final { std::cout << "Bark\r\n"; }
~Dog() = default;
};
template<typename baseType, typename derivedType>
std::unique_ptr<derivedType> dynamicConvert(std::unique_ptr<baseType> baseObj)
{
auto tmp = dynamic_cast<derivedType*>(baseObj.get());
std::unique_ptr<derivedType> derivedPointer;
if (tmp != nullptr)
{
baseObj.release();
derivedPointer.reset(tmp);
}
return derivedPointer;
}
int main()
{
auto cat = std::make_unique<Cat>();
auto base = dynamicConvert<Cat, Animal>(std::move(cat));
base->makeSound();
auto dog = dynamicConvert<Animal, Dog>(std::move(base));
dog->makeSound();
return 0;
}
输出:
I am an animal
I am a Cat
Meaow
Bark
你不能,这是与 static_cast
的合同的一部分。它在编译时解决,因此不会在运行时检查你没有犯错:转换为错误的类型只会触发 UB。
如果需要运行时检查的转换,请使用 dynamic_cast
。
我只是从基础 class 创建了两个派生 class。 然后创建一个派生class的对象并转换为基础class。 然后从基数 class 转换为派生的 class 第二个, 我希望它不会起作用,但它确实起作用了。 有人能解释一下下面的代码是如何工作的吗……我该如何防止这种情况发生……
PS:现在编辑程序使其更有意义。 这也是我想尽可能避免的情况:
class Animal
{
public:
Animal() { std::cout << "I am an animal\r\n"; };
virtual void makeSound() = 0;
~Animal() = default;
};
class Cat : public Animal
{
public:
Cat() { std::cout << "I am a Cat\r\n"; };
void makeSound() final { std::cout << "Meaow\r\n"; }
~Cat() = default;
};
class Dog : public Animal
{
public:
Dog() { std::cout << "I am a Dog\r\n"; };
void makeSound() final { std::cout << "Bark\r\n"; }
~Dog() = default;
};
template<typename baseType, typename derivedType>
std::unique_ptr<derivedType> dynamicConvert(std::unique_ptr<baseType> baseObj)
{
auto tmp = dynamic_cast<derivedType*>(baseObj.get());
std::unique_ptr<derivedType> derivedPointer;
if (tmp != nullptr)
{
baseObj.release();
derivedPointer.reset(tmp);
}
return derivedPointer;
}
int main()
{
auto cat = std::make_unique<Cat>();
auto base = dynamicConvert<Cat, Animal>(std::move(cat));
base->makeSound();
auto dog = dynamicConvert<Animal, Dog>(std::move(base));
dog->makeSound();
return 0;
}
输出:
I am an animal
I am a Cat
Meaow
Bark
你不能,这是与 static_cast
的合同的一部分。它在编译时解决,因此不会在运行时检查你没有犯错:转换为错误的类型只会触发 UB。
如果需要运行时检查的转换,请使用 dynamic_cast
。