我正在学习c ++。 我想尝试向下转换一个接口类;虽然我已经学会了铸造可能是由于糟糕的编程设计造成的。
有些网站说"使用dynamic_cast检查向下投射的有效性"。但是,在我的情况下,我不需要检查有效性,因为我可以保证它是从基类到派生类的向下转换。我在以下示例代码中尝试了dynamic_cast和static_cast。而且效果很好。
当我能保证它是一个有效的向下投射时,我可以使用static_cast吗?
示例代码:
struct Parent_Interface {
virtual ~Parent_Interface() {};
virtual void print(void) = 0;
};
struct Child : public Parent_Interface {
virtual ~Child() {};
void print(void) override {
std::cout << "Child::print()." << std::endl;
}
};
void StaticDownCastToChild(Parent_Interface& parent_interface) {
auto& child0 = static_cast<Child&>(parent_interface);
std::cout << "StaticDownCastToChild : ";
child0.print();
}
void DynamicDownCastToChild(Parent_Interface& parent_interface) {
auto& child0 = dynamic_cast<Child&>(parent_interface);
std::cout << "DynamicDownCastToChild : ";
child0.print();
}
void test_static_cast_down_cast(void) {
Child c;
StaticDownCastToChild(c);
DynamicDownCastToChild(c);
}
执行test_static_cast_down_cast()的输出。
StaticDownCastToChild : Child::print().
DynamicDownCastToChild : Child::print().
答案 0 :(得分:4)
有些网站说“使用dynamic_cast检查向下转换的有效性”。但是,在我的情况下,我不需要检查有效性,因为我可以保证它是从基类到派生类的向下转换。
正确。
如果我能保证它是一个有效的向下投射,我可以使用static_cast吗?
是
事实上,你应该,因为它是“免费的”。 dynamic_cast
经常涉及一些运行时开销。
但是,您可能希望dynamic_cast
放在assert
旁边,以便更好地衡量。请记住,这对您的发布版本没有任何影响,但如果出现严重错误,可能会在调试期间为您提供帮助。我职业生涯中一些最令人满意的时刻涉及到一个意外的assert
射击,导致一个非常快速的错误修复过程;替代方案可能是几个月的痛苦和猜测!
答案 1 :(得分:3)
有些网站说......
不介意某些网站说。标准(working draft)说:
类型为“cv1 B”的左值,其中B是类类型,可以强制转换为“引用cv2 D”,其中D是从B派生的类,如果cv2与cv-qualified相同,或者比cv1更高的cv资格。
此外,它包含的示例与您要求的几乎相同:
struct B { };
struct D : public B { };
D d;
B &br = d;
static_cast<D&>(br); // produces lvalue to the original d object
因此我会说是的,你可以这样做。
这种演员有很多用途。例如,CRTP惯用法是一种情况,您可以确切地知道派生类的类型,并且您不希望通过使用dynamic_cast
来检查强制转换是否有效。您的案例可能是另一个案例(如果没有原始代码,很难说)。
答案 2 :(得分:0)
如果我能保证它是一个有效的向下投射,我可以使用static_cast吗?
是的,你可以。也就是说,您知道演员表的情况将是有效的,但您无法指定更具体的类型(例如Child&
)不应该经常出现。当您知道您总是通过后者时,我无法想到您使用Parent_Interface&
代替Child&
的原因。