9.9.5 类和程序集(1)
C++(www.cppentry.com)/CLI应用程序总是驻留在一个或多个程序集中,因此C++(www.cppentry.com)/CLI类也要驻留在某个程序集中。我们迄今为各个示例定义的类都包含在单个简单的可执行程序集中,但我们也可以创建程序集来包含自己的类库。C++(www.cppentry.com)/CLI为类添加了确定某个类能否从驻留的程序集外部访问的可见性说明符,类驻留的程序集被称为该类的父程序集。除了本地C++(www.cppentry.com)所有的public、private和protected成员访问说明符以外,C++(www.cppentry.com)/CLI还为类成员添加了几个确定在不同的程序集中可以从什么位置访问类成员的访问说明符。
1. 类和接口的可见性说明符
我们可以将非嵌套类、接口或枚举类型的可见性指定为private或public。public类在驻留的程序集外部是可见和可以访问的,而private类只能从父程序集中访问。类、接口和枚举类型默认都是私有的,因此仅在其父程序集中才可见。如果要将某个类指定为public,我们只需像下面这样使用public关键字即可:
- public interface class IContainer
- {
- // Details of the interface...
- };
此处的IContainer接口在外部的程序集中是可见的,因为我们已经将其定义成public。如果省略public关键字,该接口默认将是私有的,只能在其父程序集内部使用。如果愿意,我们可以显式将类、枚举类型或接口指定为private,但这样做没有必要。
2. 类和接口成员的访问说明符
C++(www.cppentry.com)/CLI添加了3个类成员访问说明符:internal、public protected和private protected。这些说明符的作用在下面这个类定义的注释中有详细说明:
- public ref class MyClass // Class visible outside assembly
- {
- public:
- // Members accessible from classes inside and outside the parent assembly
-
- internal:
- // Members accessible from classes inside the parent assembly
-
- public protected:
- // Members accessible in types derived from MyClass outside the parent
- // assembly and in any classes inside the parent assembly
-
- private protected:
- // Members accessible in types derived from MyClass inside the parent
- // assembly
- };
显然,由于类定义中包含允许从父程序集外部访问的成员访问说明符,因此该类必须是公有的。在访问说明符时涉及两个关键字的位置-- 比如private protected,限制性少的关键字应用于程序集内部,限制性多的关键字应用于程序集外部。这种关键字对的顺序可以颠倒,因此protected private与private protected意义相同。
为了使用这些说明符,我们需要创建一个由多个程序集组成的应用程序。因此,我们接下来就重新创建Ex9_15,这次该程序由一个类库程序集和一个使用该类库的应用程序程序集组成。
试一试:创建类库
为了创建类库,我们可以使用Class Library模板首先创建一个名为Ex9_16lib的CLR项目。该项目包含一个内容如下的头文件Ex9_16lib.h:
- // Ex9_16lib.h
-
- #pragma once
-
- using namespace System;
-
- namespace Ex9_16lib
- {
- public ref class Class1
- {
- // TODO: Add your methods for this class here.
- };
- }
类库有其自己的命名空间,这里的命名空间默认是Ex9_16lib。如果愿意,我们可以将其改为某个更合适的名称。库中的类名由该命名空间名限定,因此我们需要在访问库中任何类的任何外部源文件中添加该命名空间名的using指令。库中类的定义位于该命名空间的大括号之间。该命名空间内已经默认定义了一个引用类,但我们应该用自己的类将其替换掉。注意,Class1类被指定为public,在另一个程序集中可见的所有类都必须被指定为public。
将Ex9_16lib.h的内容修改为:
- // Ex9_16lib.h
-
- #pragma once
-
- using namespace System;
-
- namespace Ex9_16lib
- {
- // IContainer.h for Ex9_16
- public interface class IContainer
- {
- virtual double Volume(); // Function for calculating a volume
- virtual void ShowVolume(); // Function to display a volume
- };
-
- // Box.h for Ex9_16
- public ref class Box : IContainer
- {
- public:
- // Function to show the volume of an object
- virtual void ShowVolume()
- {
- Console::WriteLine(L"CBox usable volume is {0}", Volume());
- }
-
- // Function to calculate the volume of a Box object
- virtual double Volume()
- { 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){}
- public protected:
- double m_Length;
- double m_Width;
- double m_Height;
- };
-
- // Stack.h for Ex9_16
- public 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 box from item
- TopTop = Top->Next; // Make next item the top
- return obj;
- }
- };
- }