9.9.2 C++(www.cppentry.com)/CLI类的继承(1)
虽然数值类总是以System::Object为基类,但我们不能定义派生自现有类的数值类。换句话说,我们在定义数值类时不能指定基类。这意味着数值类中的多态性仅限于在System::Object类中被定义为虚函数的那些函数。表9-2给出了所有数值类都要从System::Object类继承的虚函数。
表 9-2
|
函 数< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> |
说 明 |
|
String^ ToString() |
返回对象的String表示法,System::Object
类中的实现返回字符串形式的类名。我们
通常要在自己的类中重写该函数,以返
回对象值的字符串表示 |
|
bool Equals(Object^ obj) |
比较当前对象与obj,如果二者相等则
返回true,否则返回false。这里的“相等”
意味着引用相等性—— 即两个对象是同一个。
我们通常要在自己的类中重写该函数,以便
当前对象与实参的值相等时,即二者的字段
相等时返回true |
|
int GetHashCode() |
返回当前对象的散列码—— 一个整数。
在存储(key,object)对的集合中,散列码用
作存储对象的键码。随后,我们通过提
供某个对象被存储时使用的键码,就
可以从这样的集合中将该对象检索出来 |
当然,因为System::Object也是引用类的基类,所以我们在引用类中也需要重写这些函数。
以定义本地C++(www.cppentry.com)派生类时所用的相同方式,我们可以从现有的引用类派生出新的引用类。让我们重新以C++(www.cppentry.com)/CLI程序的形式实现Ex9_12,该示例还示范了CLR程序中嵌套类的用法。我们可以首先定义Container类:
- // Container.h for Ex9_14
- #pragma once
- using namespace System;
-
- // Abstract base class for specific containers
- ref class Container abstract
- {
- public:
- // Function for calculating a volume - no content
- // This is defined as an 'abstract' virtual function,
- // indicated by the 'abstract' keyword
- virtual double Volume() abstract;
-
- // Function to display a volume
- virtual void ShowVolume()
- {
- Console::WriteLine(L"Volume is {0}", Volume());
- }
- };
首先需要注意的是类名后面的abstract关键字。如果某个C++(www.cppentry.com)/CLI类包含等价于本地C++(www.cppentry.com)类中纯虚函数的函数,那么我们必须将该类指定为abstract。当然,也可以将不包含任何抽象函数的类指定为abstract,这样可以阻止该类的对象被创建。abstract关键字还出现在Volume()函数成员声明的最后,以指出该函数是为本抽象类定义的。我们也可以像在本地C++(www.cppentry.com)类中那样,在Volume()声明的最后添加"= 0",但这样做不必要。
这里的Volume()和ShowVolume()函数都是虚函数,因此可以从Container派生的类类型的对象中多态地调用它们。
我们可以像下面这样定义Box类:
- // Box.h for Ex9_14
- #pragma once
- #include "Container.h" // For Container definition
-
- ref class Box : Container // Derived class
- {
- public:
- // Function to show the volume of an object
- virtual void ShowVolume() override
- {
- Console::WriteLine(L"Box usable volume is {0}", Volume());
- }
-
- // Function to calculate the volume of a Box object
- virtual double Volume() override
- { return m_Length*m_Width*m_Height; }
-
- // Constructor
- Box() : m_Length(1.0), m_Width(1.0), m_Height(1.0){}
-
- // Constructor
- Box(double lv, double wv, double hv)
- : m_Length(lv), m_Width(wv), m_Height(hv){}
- protected:
- double m_Length;
- double m_Width;
- double m_Height;
- };
引用类的基类总是公有的,默认情况下编译器认为是有public关键字的。我们可以显式地将基类指定为public,但这样做是不必要的。引用类的基类不能被指定为除public以外的任何东西。因为我们不能像在该类的本地C++(www.cppentry.com)版本中那样给形参提供默认值,所以定义了一个将所有3个字段初始化为1.0的无参数构造函数。Box类重写了从基类继承的Volume()函数。当需要重写基类中的某个函数时,我们必须总是指定override关键字。如果Box类不实现Volume()函数,那么它将是一个抽象类,而为了成功编译这个类,则需要将其指定为abstract。
下面是GlassBox类定义的代码:
- // GlassBox.h for Ex9_14
- #pragma once
- #include "Box.h" // For Box
-
- ref class GlassBox : Box // Derived class
- {
- public:
- // Function to calculate volume of a GlassBox
- // allowing 15% for packing
- virtual double Volume() override
- { return 0.85*m_Length*m_Width*m_Height; }
-
- // Constructor
- GlassBox(double lv, double wv, double hv): Box(lv, wv, hv){}
- };