9.9.5 类和程序集(2)
IContainer接口类、Box类和Stack类现在都位于这个类库中。这些类中对原来的定义所作的修改以阴影标识。3个类现在都是公有的,因此外部程序集可以访问它们。Box类中的字段是public protected,这意味着派生类继承的这些字段将变为protected,但就父程序集内部的类来说,它们都是public字段。我们实际上没有从父程序集内部的其他类中引用这些字段,因此本例中将Box类中的字段指定为protected也是可以的。
当我们成功编译该项目之后,包含该类库的程序集在Ex9_16lib.dll文件中。如果编译的是项目的调试版本,则该文件位于项目目录的debug子目录中。如果编译的是发布版本,则该文件位于release子目录中。.dll扩展名意味着这是个动态链接库或DLL。现在,我们需要另一个使用该类库的项目。
试一试:使用类库
同前面一样,添加一个名为Ex9_16、自带解决方案的CLR控制台项目。然后,我们可以将Ex9_16.cpp修改成下面这样:
- // Ex9_16.cpp : main project file.
- // Using a class library in a separate assembly
- #include "stdafx.h"
- #include "GlassBox.h"
- #using <Ex9_16lib.dll>
-
- using namespace System;
- using namespace Ex9_16lib;
-
- int main(array<System::String ^> ^args)
- {
- array<IContainer^>^ containers = { 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 containers
have the following volumes:"); - for each(IContainer^ container in containers)
- container->ShowVolume(); // Output the volume of a box
-
- Console::WriteLine(L"\nNow pushing the containers on the stack...");
-
- Stack^ stack = gcnew Stack; // Create the stack
- for each(IContainer^ container in containers)
- stack->Push(container);
-
- Console::WriteLine(
- L"Popping the containers off the stack
presents them in reverse order:"); - Object^ item;
- while((item = stack->Pop()) != nullptr)
- safe_cast<IContainer^>(item)->ShowVolume();
-
- Console::WriteLine();
- return 0;
- }
我们还需要向该项目添加其代码与Ex9_15中相同的GlassBox.h头文件。可以将该文件复制到本项目的目录中,然后通过右击Solution Explorer选项卡中的Header Files,并从上下文菜单中选择Add | Existing Item,从而将其添加到项目中。当然,GlassBox类是从Box类派生而来的,因此编译器需要知道去哪里寻找Box类的定义。本例中,Box类定义位于上一个项目创建的类库中,因此将下面这条指令添加到GlassBox.h头文件中#pragma once指令之后:
- #using <Ex9_16lib.dll>
Box类名是在Ex9_16lib命名空间内定义的,因此在这条#using指令之后我们还需要添加一条using语句:
- using namespace Ex9_16lib;
为了使编译器能够找到Ex9_16lib类库,将Ex9_16lib项目中的Ex9_16lib.dll文件复制到包含Ex9_16.exe文件的Ex9_16解决方案目录的debug子目录中。我们可以在#using指令中指定该程序集的全路径,但更常见的方法是将某个项目使用的任何类库都放入包含应用程序可执行文件的目录中。这时很容易把目录搞乱。Ex9_16lib.dll文件在Ex9_16lib解决方案目录的debug子目录中,而不是在Ex9_16lib项目目录的debug子目录中。我们需要将这个库文件复制到Ex9_16解决方案目录的debug子目录中。确保将该.dll文件复制到正确的目录中,否则编译器将找不到这个库。
因为外部程序集中的这些类都在各自的命名空间中,所以我们为命名空间Ex9_16lib添加一条using指令。如果没有这条指令,我们将不得不用命名空间名来限定IContainer、Box和Stack这几个类名,因此必须写成Ex9_16lib::Box而非简单的Box。
代码的其余部分完全与Ex9_15项目的main()函数相同。任何修改都不需要,因为现在我们无非是在使用来自外部程序集的类。如果执行该程序,输出将与Ex9_15示例的输出相同。