你检索你的对象是这样的:
Libitem* old_book = catalog[1];
就这样,编译器只知道你有一个名为类型的old_book
指针Libitem
变量。如果你自己单独阅读特定行,你会注意到,唯一的这是你和编译器当时唯一的信息。当你自己读这行的时候就是编译时间。通过阅读代码你可以知道什么。
当程序实际运行,该变量可以指向Book
类型的对象。但是这只在程序运行时才知道,因此,运行时间。
名称查找发生在C++编译时。当你调用一个函数的对象上是这样的:
// Type of an_object is a_struct
a_struct an_object;
an_object.member_function();
编译器将着眼于可用的功能里面a_struct
。由于编译器正在声明结构体中的名称,所以在编译时真正解析了名称。
让我们回到你的案例。你有一个指向Libitem
的指针。如果您尝试使用箭头来访问它里面的东西:
old_book->something
要解决什么something
是,编译器会往里Libitem
它,因为old_book
类型是一个指向Libitem
。即使指针指向一个子类的实例,唯一的编译器知道肯定是对象的实际类型指出,至少Libitem
。现在
,你的人知道比编译器的更多。你知道指针old_book
指向类Book
的一个实例。您想访问Book
的会员。
为此,您必须明确告诉编译器您想使用来自子类的成员。要做到这一点,你的变量必须是Book
的类型,所以编译器会查找适当的类。为此,您可以将您的变量转换为另一种类型。由于您将变量转换为层次结构中较低级别的变量,因此将其称为向下倾斜。那种铸铁的,我们可以在这种情况下使用是dynamic_cast
,一个演员,其中将着眼于运行的是由指针所指向的实际类型的实例:
if (Book* the_old_book = dynamic_cast<Book*>(old_book)) {
// We can use the_old_book here, which his type is Book!
} else {
// The cast failed, the real for of the variable is not Book,
// and the_old_book points to nullptr
}
正如你所看到的,我们创建了一个新的指针名为the_old_book
,它由演员的结果初始化。如果old_book
指向的实例的实际类型实际上不是Book
,则该投射将失败并返回nullptr
。由于这发生在运行时,我们必须使用运行时分支验证我们的新变量,if
。如果转换失败,则执行的块将为else
块。
请搜索并阅读关于* downcasting *。 –