// use Brass: : ViewAcct ()

// use Brass: : ViewAcct ()
// use BrassPlus: : ViewAcct ()

// use Brass: : ViewAcct ()
// use Brass: : ViewAcct ()

/7 use Brass: : ViewAcct ()
// use BrassPlus: : ViewAcct ()

● Brass类在声明ViewAcct()和Withdraw()时使用了新关键字virtual。这些方法被称为虚方法(virtual
method)
● Brass 类还声明了 ·个虚拟析构函数,虽然该析构函数不执行任何操作。
第一点没有什么新鲜的。RatedPlayer类在TableTennisPlayer类的基础上添加新数据成员和2个新方法
的方式与此类似。
第二点介绍了声明如何指出方法在派生类的行为的不同。两个ViewAcct()原型表明将有2个独立的方
法定义。基类版本的限定名为 Brass :: ViewAcct(),派生类版本的限定名为 BrassPlus :: ViewAcct()。程序将
使用对象类型来确定使用哪个版本:
Brass dom !"Dominic Banker", 11224. 4183.45) :
BrassPlun dot ("Dorothy Banker". 12118, 2592.00/ :
com. ViewAcet O):
dot .. ViewAcct O:
同样,Withdraw(也有2个版本,个供Brass对象使用,另一个供BrassPlus对象使用。对于在两个
类中行为相同的方法(如Deposit()和Balance(),则只在基类中声明。
第点:使用 virtual)比前两点要复杂。如果方法是通过引用或指针而不是对象调用的,它将确定使
用哪 种方法.如果没有使用关键字virtual,程序将根据引用类型或指针类型选择方法:如果使用了 virtual,
程序将根据引用或指针指向的对象的类型来选择方法。如果ViewAcct()不是虚拟的,则程序的行为如下:
// behavior with non-virtual ViewAcct ()
// method chosen according to reference type
Brass dom r"Dominic Banker". 11224. 4183.45) :
BrassPlus dot |"Dorothy Banker", 12118. 2592.00) :
Brass & bl ref = dom:
Brass & b2 ref = dot:
b1 ref.ViewAcct():
b2 ref.ViewAcct ():
引用变量的类型为Brass,所以选择了Brass :: ViewAccount()。使用Brass 指针代替引用时,行为将与
此类似。
如果ViewAcct()是虚拟的,则行为如下:
// behavior with virtual ViewAcet ()
// method chosen according to object type
Brass dom ("Dominic Banker". 11224. 4183.451 :
BrassPlus dot ("Dorothy Banker". 12118. 2592.00) ;
Brass & bl ref = dom:
Brass & b2 ref = dot:
hl ref.ViewAcct(l:
h2 rpf. ViewAcct ():
这里两个引用的类型都是 Brass,但b2 ref 引用的是 ·个 BrassPlus 对象,所以使用的是
BrassPlus :: ViewAcct()。使用Brass指针代替引用时,行为将类似。
稍后您将看到,虚函数的这种行为非常方便。因此,经常在基类中将派生类会重新定义的方法声明为
虚方法,方法在基类中被声明为虚拟的后,它在派生类中将自动成为虚方法。不过,在派生类声明中使用
关键了virtual来指出哪些函数是虚两数也不失为·个好办法。
第四点是,基类声明了 ·个虚拟析构函数。这样做是为了确保释放派生对象时,按正确的顺序调用析
构函数。本章后面将详细介绍这个问题。
记住:如果要在派生类中重新定义基类的方法,通常应将基类方法声明为虚拟的,这样,程序将根据
对象类型而不是引用或指针的类型来选择方法版本,为基类声明一个虚拟析构函数也是一种惯例,

1. 类实现
接下来需要实现类,其中的部分工作已由头文件中的内联函数定义完成了。程序清单13.8列出了其他
方法的定义。注意,关键字virtual只用于类声明的方法原型中,而没有用于程序清单13.8的方法定义中。