9.9.2 C++(www.cppentry.com)/CLI类的继承(2)
默认的public基类是Box。该类的其余部分实质上与以前相同。
下面是Stack类的定义:
- // Stack.h for Ex9_14
- // A push-down stack to store objects of any ref class type
- #pragma once
-
- ref class Stack
- {
- private:
- // Defines items to store in the stack
- ref struct Item
- {
- Object^ Obj; // Handle for the object in this item
- Item^ Next; // Handle for next item in
the stack or nullptr -
- // Constructor
- Item(Object^ obj, Item^ next): Obj(obj), Next(next){}
- };
-
- Item^ Top; // Handle for item that is at the top
-
- public:
- // Push an object on to the stack
- void Push(Object^ obj)
- {
- Top = gcnew Item(obj, Top); // Create new
item and make it the top - }
-
- // Pop an object off the stack
- Object^ Pop()
- {
- if(Top == nullptr) // If the stack is empty
- return nullptr; // return nullptr
-
- Object^ obj = Top->Obj; // Get object from item
- TopTop = Top->Next; // Make next item the top
- return obj;
- }
- };
需要注意的第一点区别是函数的形参和字段现在都是句柄,因为我们是在处理引用类对象。内部的结构Item现在存储着Object^类型的句柄,这样的句柄允许在堆栈中存储任何CLR类类型的对象,这意味着无论是数值类还是引用类都能被压入堆栈-- 这一点是对本地C++(www.cppentry.com)中CStack类的重大改进。我们不必担心调用Pop()函数时删除Item对象的问题,因为这项任务由垃圾回收器负责。
下面总结了这些类同本地C++(www.cppentry.com)类的区别:
只有引用类可以是派生类。
派生引用类的基类始终都是public。
引用类中没有定义的函数是抽象函数,必须使用abstract关键字声明。
我们必须通过在类名后面放上abstract关键字,将包含一个或多个抽象函数的类显式指定为抽象类。
不包含抽象函数的类也可以被指定为abstract,这种情况下我们将不能定义该类的实例。
当指定某个重写基类函数的函数时,我们必须显式使用override关键字。
试验这些类只需一个包含main()定义的CLR控制台项目即可,下面我们就来完成该项目。
试一试:使用派生的引用类
创建一个名为Ex9_14的CLR控制台项目,将前面几个类添加到该项目中,然后给Ex9_14.cpp文件添加下面的内容:
- // Ex9_14.cpp : main project file.
- // Using a nested class to define a stack
-
- #include "stdafx.h"
- #include "Box.h" // For Box and Container
- #include "GlassBox.h" // For GlassBox (and Box and Container)
- #include "Stack.h" // For the stack class with nested struct Item
-
- using namespace System;
-
- int main(array<System::String ^> ^args)
- {
- array<Box^>^ boxes = { gcnew Box(2.0, 3.0, 4.0),
- gcnew GlassBox(2.0, 3.0, 4.0),
- gcnew Box(4.0, 5.0, 6.0),
- gcnew GlassBox(4.0, 5.0, 6.0)
- };
- Console::WriteLine(L"The array of boxes have the following volumes:");
- for each(Box^ box in boxes)
- box->ShowVolume(); // Output the volume of a box
-
- Console::WriteLine(L"\nNow pushing the boxes on the stack...");
-
- Stack^ stack = gcnew Stack; // Create the stack
- for each(Box^ box in boxes)
- stack->Push(box);
-
- Console::WriteLine(
- L"Popping the boxes off the stack presents them in reverse order:");
- Object^ item;
- while((item = stack->Pop()) != nullptr)
- safe_cast<Container^>(item)->ShowVolume();
-
- Console::WriteLine(L"\nNow pushing integers on to the stack:");
- for(int i = 2 ; i<=12 ; i += 2)
- {
- Console::Write(L"{0,5}",i);
- stack->Push(i);
- }
-
- Console::WriteLine(L"\n\nPopping integers off the stack produces:");
- while((item = stack->Pop()) != nullptr)
- Console::Write(L"{0,5}",item);
-
- Console::WriteLine();
- return 0;
- }