你认为这一计划将输出?
让我们看看这个过程是如何。首先,我们实例化一个类的对象。rbase是一个指针,我们设置为指向的对象的一部分。最后,我们称rbase getname()。rbase getname()。计算结果为::getname()。然而,一个::getname()是虚拟的,所以编译器将检查所有A和C之间的类是否能找到一个更衍生得到的匹配。首先,它检查B::getname(),并找到一个匹配。然后检查C::getname()和找到一个更好的匹配。它不检查D::getname()因为我们原来的对象是一个C,不是一个D。因此,rbase。getname()解决C::getname()。
因此,我们的程序的输出:
rbase是C
一个更复杂的例子
让我们看看另一个动物的例子我们的工作与在上一课。这里的原始类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
#include <string>
class
Animal
{
protected
:
std::string m_strName;
// We're making this constructor protected because
// we don't want people creating Animal objects directly,
// but we still want derived classes to be able to use it.
Animal(std::string strName)
: m_strName(strName)
{
}
public
:
std::string GetName() {
return
m_strName; }
const
char
* Speak() {
return
"???"
; }
};
class
Cat:
public
Animal
{
public
:
Cat(std::string strName)
: Animal(strName)
{
}
const
char
* Speak() {
return
"Meow"
; }
};
class
Dog:
public
Animal
{
public
:
Dog(std::string strName)
: Animal(strName)
{
}
const
char
* Speak() {
return
"Woof"
; }
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
#include <string>
class
Animal
{
protected
:
std::string m_strName;
// We're making this constructor protected because
// we don't want people creating Animal objects directly,
// but we still want derived classes to be able to use it.
Animal(std::string strName)
: m_strName(strName)
{
}
public
:
std::string GetName() {
return
m_strName; }
virtual
const
char
* Speak() {
return
"???"
; }
};
class
Cat:
public
Animal
{
public
:
Cat(std::string strName)
: Animal(strName)
{
}
virtual
const
char
* Speak() {
return
"Meow"
; }
};
class
Dog:
public
Animal
{
public
:
Dog(std::string strName)
: Animal(strName)
{
}
virtual
const
char
* Speak() {
return
"Woof"
; }
};
|
请注意,我们不做动物::getname()虚拟。这是因为getname()是从来没有在任何派生类中重写,因此没有必要。
现在,使用虚拟speak()功能,下面的功能应正常工作:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
void
Report(Animal &rAnimal)
{
cout << rAnimal.GetName() <<
" says "
<< rAnimal.Speak() << endl;
}
int
main()
{
Cat cCat(
"Fred"
);
Dog cDog(
"Garbo"
);
Report(cCat);
Report(cDog);
}
|
事实上,这个程序产生的结果:
弗莱德说,喵
嘉宝说汪
当canimal。speak()评估程序,指出它是一个虚函数。在的情况下,ranimal指着一只猫的动物部分对象,程序会在所有的动物和猫之间的类是否能找到更多的衍生功能。在这种情况下,它发现猫::speak()。在的情况下,ranimal指出,狗的动物部分对象,程序解析函数的调用speak()狗:。
同样的,下面的数组的例子现在正常工作:
1
2
3
4
5
6
7
|
Cat cFred(
"Fred"
), cTyson(
"Tyson"
), cZeke(
"Zeke"
);
Dog cGarbo(
"Garbo"
), cPooky(
"Pooky"
), cTruffle(
"Truffle"
);
// Set up an array of pointers to animals, and set those pointers to our Cat and Dog objects
Animal *apcAnimals[] = { &cFred, &cGarbo, &cPooky, &cTruffle, &cTyson, &cZeke };
for
(
int
iii=0; iii < 6; iii++)
cout << apcAnimals[iii]->GetName() <<
" says "
<< apcAnimals[iii]->Speak() << endl;
|