语句 | 解释章节 |
---|---|
int A::b(int c) { } | 类 |
a->b | 数据结构 |
class A: public B {}; | 友元和继承 |
|
|
20 10 |
main
声明了两个指向 Polygon
的指针(名为 ppoly1
和 ppoly2
)。它们被分别赋予了 rect
和 trgl
的地址,这两个对象分别是 Rectangle
和 Triangle
类型的。这样的赋值是有效的,因为 Rectangle
和 Triangle
都是从 Polygon
派生出来的类。ppoly1
和 ppoly2
(使用 ppoly1->
和 ppoly2->
)是有效的,并允许我们访问它们所指向对象的成员。例如,在前面的例子中,以下两个语句是等价的:
|
|
ppoly1
和 ppoly2
的类型都是指向 Polygon
的指针(而不是指向 Rectangle
或指向 Triangle
的指针),所以只能访问从 Polygon
继承的成员,而不能访问派生类 Rectangle
和 Triangle
的成员。这就是为什么上面的程序直接使用 rect
和 trgl
来访问两个对象的 area
成员,而不是通过指针;指向基类的指针无法访问 area
成员。area
是 Polygon
的成员而不是其派生类的成员,那么就可以通过指向 Polygon
的指针来访问 area
成员。但问题是,Rectangle
和 Triangle
实现了不同版本的 area
,因此没有一个通用的版本可以在基类中实现。virtual
关键字。
|
|
20 10 0 |
Polygon
、Rectangle
和 Triangle
)都有相同的成员:width
、height
,以及函数 set_values
和 area
。area
在基类中被声明为 virtual
,因为它之后在每个派生类中被重新定义。非虚成员也可以在派生类中被重新定义,但派生类的非虚成员不能通过基类的引用来访问。也就是说,如果在上面的例子中从 area
的声明中移除 virtual
,那么所有三次对 area
的调用都将返回零,因为在所有情况下,被调用的都将是基类的版本。virtual
关键字本质上所做的,是允许派生类中与基类中同名的成员能够通过指针被正确调用,更确切地说,是当指针类型为指向基类的指针,而它正指向派生类的对象时,就像上面的例子一样。Polygon
的一个成员是虚函数,但它仍然是一个常规类,甚至可以实例化一个对象(poly
),它有自己对成员 area
的定义,该定义总是返回 0。Polygon
类非常相似。它们是只能用作基类的类,因此允许拥有没有定义的虚成员函数(称为纯虚函数)。其语法是用 =0
(一个等号和一个零)来替换其定义。Polygon
可能看起来像这样:
|
|
area
没有定义;它被 =0
所取代,这使其成为一个纯虚函数。包含至少一个纯虚函数的类被称为抽象基类。Polygon
不能用于声明像下面这样的对象:
|
|
|
|
|
|
20 10 |
Polygon*
)来引用,并且每次都会调用正确的成员函数,仅仅因为它们是虚函数。这在某些情况下非常有用。例如,抽象基类 Polygon
的一个成员甚至可以使用特殊指针 this
来访问正确的虚成员,即使 Polygon
本身没有实现这个函数。
|
|
20 10 |
|
|
20 10 |
ppoly
指针:
|
|
Polygon
的指针”类型,但分配的对象则直接声明为派生类的类型(Rectangle
和 Triangle
)。![]() 友元和继承 | ![]() 目录 | ![]() 类型转换 |