运行时多态性和 dynamic_cast 需要澄清
runtime polymorphism and dynamic_cast need clarification
可能在其他地方回答了一些问题,但找不到合适的短语来提问
所以听到了。
我有基础 class A
,有 child B
和 C
; (完全用于培训目的)
#include <iostream>
class A
{
public:
virtual void print () { std::cout<< "A::print()" << std::endl; }
};
class B: public A
{
public:
void print () { std::cout<< "B::print()" << std::endl; }
};
class C : public B
{
public:
void print () { std::cout<< "C::print()" << std::endl; }
};
所以,在我的 main 中,我声明了基指针 A*
bptr;后来 child 的 B
和 C
也宣布了。
稍后 bPtr 指向 B
并调用 print
函数按预期工作;
后来 bPtr 指向 C
并调用 print
函数按预期工作;
听到的是代码,没问题听到。
int main()
{
A* bPtr;
B b;
C c;
bPtr = &b;
bPtr->print(); // prints B::print() - as expected;
bPtr = &c;
bPtr->print(); // prints C::print() - as expected;
}
听说是我的困境,我可能理解错了;
现在我这些天一直在想, dynamic_cast
也确实在上面;
但情况有所不同,或者我做错了什么。
int main()
{
A* bPtr = new C;
bPtr = dynamic_cast<B*>( bPtr );
bPtr->print(); // prints C::print() - expected B::print()
/*
I know above can be correct with explicit call
*/
(dynamic_cast<B*>( bPtr ))->B::print(); // B::print
bPtr = dynamic_cast<C*>( bPtr );
bPtr->print(); // prints C::print()
return 0;
if ( B* b = dynamic_cast<B*>( bPtr ))
{
b->print(); // still calls C::print() anyway;
}
}
所以听到的是我的问题是 dynamic_cast
good for and only places like if
statement to determine
base 和 child 之间是否存在继承或 base 和 child 之间是否存在安全转换?
if ( B* b = dynamic_cast<B*>( bPtr ))
{
b->print(); // still calls C::print() anyway;
}
此行为与dynamic_cast无关。
虚拟调用的行为将始终取决于值的实际运行时类型。在您的第二个示例中,实际构造的唯一东西是 C
,因此所有调用都将解析为 C,无论您将其称为 A:A * a = bPtr
还是 B:B * b = bPtr
,它都会解析为 C::print() 因为语句 new C
将实际值构造为 C.
Dynamic_cast 只是将给定的值转换为特定类型,如果它是该类型的(子类型),否则 return nullptr
。因此,将 B *
动态转换为 C *
将失败并且 return nullptr
,但在您的情况下,您正在将 C *
转换为其基本类型之一,这将永远成功,永远不会改变价值本身。
可能在其他地方回答了一些问题,但找不到合适的短语来提问
所以听到了。
我有基础 class A
,有 child B
和 C
; (完全用于培训目的)
#include <iostream>
class A
{
public:
virtual void print () { std::cout<< "A::print()" << std::endl; }
};
class B: public A
{
public:
void print () { std::cout<< "B::print()" << std::endl; }
};
class C : public B
{
public:
void print () { std::cout<< "C::print()" << std::endl; }
};
所以,在我的 main 中,我声明了基指针 A*
bptr;后来 child 的 B
和 C
也宣布了。
稍后 bPtr 指向 B
并调用 print
函数按预期工作;
后来 bPtr 指向 C
并调用 print
函数按预期工作;
听到的是代码,没问题听到。
int main()
{
A* bPtr;
B b;
C c;
bPtr = &b;
bPtr->print(); // prints B::print() - as expected;
bPtr = &c;
bPtr->print(); // prints C::print() - as expected;
}
听说是我的困境,我可能理解错了;
现在我这些天一直在想, dynamic_cast
也确实在上面;
但情况有所不同,或者我做错了什么。
int main()
{
A* bPtr = new C;
bPtr = dynamic_cast<B*>( bPtr );
bPtr->print(); // prints C::print() - expected B::print()
/*
I know above can be correct with explicit call
*/
(dynamic_cast<B*>( bPtr ))->B::print(); // B::print
bPtr = dynamic_cast<C*>( bPtr );
bPtr->print(); // prints C::print()
return 0;
if ( B* b = dynamic_cast<B*>( bPtr ))
{
b->print(); // still calls C::print() anyway;
}
}
所以听到的是我的问题是 dynamic_cast
good for and only places like if
statement to determine
base 和 child 之间是否存在继承或 base 和 child 之间是否存在安全转换?
if ( B* b = dynamic_cast<B*>( bPtr ))
{
b->print(); // still calls C::print() anyway;
}
此行为与dynamic_cast无关。
虚拟调用的行为将始终取决于值的实际运行时类型。在您的第二个示例中,实际构造的唯一东西是 C
,因此所有调用都将解析为 C,无论您将其称为 A:A * a = bPtr
还是 B:B * b = bPtr
,它都会解析为 C::print() 因为语句 new C
将实际值构造为 C.
Dynamic_cast 只是将给定的值转换为特定类型,如果它是该类型的(子类型),否则 return nullptr
。因此,将 B *
动态转换为 C *
将失败并且 return nullptr
,但在您的情况下,您正在将 C *
转换为其基本类型之一,这将永远成功,永远不会改变价值本身。