当前位置:天才代写 > tutorial > C语言/C++ 教程 > 实例理会C++/CLI中的接口与泛型

实例理会C++/CLI中的接口与泛型

2017-11-06 08:00 星期一 所属: C语言/C++ 教程 浏览:499

副标题#e#

接口

某些时候,让不相关的类分享一组公有成员,以便发生沟通的行为,长短常有用的。一个最根基的要领大概是通过一个民众的基类来界说它们,但这种要领太受范围,因为它要求这些类通过担任而相互关联,别的,它们也许尚有着各自的基类,且CLI范例只支持单一类担任。

C++/CLI提供了一种要领,可操作多个类实现一组通用的成果,这就是我们通称的"接口",而一个接口则是一构成员函数的声明。要留意,这些函数只是声明,没有界说,也就是说,一个接口界说了一个由抽象函数构成的范例–这些函数实际上是纯虚函数,且在适当的时候,这些函数由客户类来实现。一个接口可答允不相关的类用同一名称和范例,实现同一成果,而无必要求这些类分享民众基类。在例1中演示了奈何界说一个接口。

例1:

using namespace System;
public interface class ICollection
{
  void Put(Object^ o); //隐式public abstract
  Object^ Get(); //隐式public abstract
};

一个接口的界说看上去很是像一个类,除了用interface代替了ref或value,所有的函数都没有函数体,且均隐式为public和abstract。凭据凡是的约定,一个接口名带有起始字母I,后再接一个大写字母。(接口类与接口布局是等价的。)与类相似,一个接口也能有public或private会见可见性。

一个接口能有一个或多个"基接口",在这种环境下,它将担任这些接口中的所有抽象函数,譬喻,在例2中,接口I2显式担任自I1,而I3显式担任自I1与I2,并通过I2隐式担任自I1。

例2:

interface class I1 { /* ... */ };
interface class I2 : I1 { /* ... */ };
interface class I3 : I1, I2 { /* ... */ };

一个类可像从基类担任时那样,来实现一个接口,见例3。

例3:

public ref class List : ICollection
{
  public:
   void Put(Object^ o)
   {
    // ...
   }
   Object^ Get()
   {
    // ...
   }
   // ...
};

一个类能实现一个以上的接口,在这种环境下,必需利用逗号来脱离接口列表,顺序倒不是很重要。虽然,一个类在实现一个或多个接口时,也能显式地带有一个基类,在这种环境下,基类凡是(但不是必需)写在最前面。

假如一个类实现了一个接口,但没有界说接口中所有的函数,这个类就必需声明为abstract。虽然了,任何从抽象类担任而来的类也是抽象类,除非界说了之前的这些抽象函数。

接口不提供多重担任,与此对比,一个CLI类也只能有一个基类,然而,接口却提供某种与多重类担任相似的成果,但观念与之完全差异,譬喻,一个类不能从接口中担任函数界说;接口担任体系是独立于类担任体系的–实现同一接口的类也许会、但也许不会通过类担任体系彼此关联。

例4演示了一个类:Queue,其与List无关联(但除了这个外,两者都是从Object担任而来的),两者都实现了同一接口。

例4:

public ref class Queue : ICollection
{
  public:
   void Put(Object^ o)
   {
    // ...
   }
   Object^ Get()
   {
    // ...
   }
   // ...
};

此刻,可用它来编写处理惩罚参数为List或Queue的函数了,如例5。

例5:

ref class Item { /* ... */ };
void ProcessCollection(ICollection^ c);
int main()
{
  List^ myList = gcnew List;
  Queue^ myQueue = gcnew Queue;
  ProcessCollection(myList);
  ProcessCollection(myQueue);
}
void ProcessCollection(ICollection^ c)
{
  Item^ x = gcnew Item();
  /*1*/ c->Put(x);
  /*2*/ x = static_cast<Item^>(c->Get());
}


#p#副标题#e#

在标号1与2中,为会见底层的List或Queue,利用了一个指向接口的句柄c,由此,你可通报给ProcessCollection一个指向任意工具的句柄,只要它的类实现了这个接口,可能它是从实现了这个接口的类担任而来的。

例6演示了一个包括只读属性X、只写属性Y、读写属性Z的接口,对读写属性来说,get与set声明的顺序并不重要。

例6:

public interface class IProperties
{
  property int X { int get(); }
  property String^ Y { void set(String^ value); }
  property Object^ Z { Object^ get(); void set(Object^ value); }
};

一个接口的成员,可觉得静态数据成员、实例或静态函数、静态结构函数、实例或静态属性、实例或静态事件、操纵符函数、或任意的嵌套范例。

一般来说,我们会用for each语句来列举荟萃中的所有元素,要对荟萃中的每个元素逐个举办操纵,可利用如下语法:

for each (表达式形式的范例标识符)

嵌入语句

表达式范例必需为一个"荟萃范例",假如要成为一个荟萃范例,这个范例必需实现接口System::Collections::IEnumerable,如例7中所界说。

例7:

public interface class IEnumerable
{
  IEnumerator^ GetEnumerator();
};

正如各人所见,GetEnumerator返回一个指向IEnumerator的句柄,如例8中所界说。

例8:

public interface class IEnumerator
{
  bool MoveNext();
  void Reset();
  property Object^ Current { Object^ get(); }
};

#p#分页标题#e#

System::Array为一个荟萃范例,因为所有的CLI数组范例都担任自System::Array,所以,任何数组范例表达式都可以作为for each语句中的表达式。在例9的标号1中,for each用于遍历一个int数组,标号2中的处理惩罚进程也一样,但直接利用了列举器。

#p#副标题#e#

例9:

using namespace System;
using namespace System::Collections;
int main()
{
  array<int>^ ary = gcnew array<int>{10, 20, 30, 40};
  /*1*/ for each (int i in ary)
  {
   Console::Write(" {0}", i);
  }
  Console::WriteLine();
  /*2*/ IEnumerator^ ie = ary->GetEnumerator();
  while (ie->MoveNext())
  {
   Console::Write(" {0}", static_cast<int>(ie->Current));
  }
  Console::WriteLine();
}

泛型

就像函数能用一个或多个范例暗示符来界说一样,范例也可以这样来界说。如果有这样一种环境,某种范例建模了一个"数组",其可利用下标来会见每个元素,这样的范例往往被称为"向量",实现一个向量之后,可以生存一组int、一组double、或一组用户自界说范例的元素。然而,正是因为每种范例实现的代码对范例中的元素来说,都是独一的,因此,可利用泛型机制来界说一个向量范例,并建设特定范例的实例。例10就是这样的一个例子。

例10:

generic <typename T>
public ref class Vector
{
  int length;
  /*1*/ array<T>^ vector;
  public:
   property int Length
   {
    int get() { return length; }
    private:
     void set(int value) { length = value; }
   }
   /*2*/ property T default[int]    {
    T get(int index) { return vector[index]; }
    void set(int index, T value) { vector[index] = value; }
   }
   Vector(int vectorLength, T initValue)
   {
    Length = vectorLength;
    vector = gcnew array<T>(Length);
    for (int i = 0; i < Length; ++i)
    {
     /*3*/ this[i] = initValue;
    }
    /*4*/ //for each (T element in vector)
    //{
     // element = initValue;
    /

 

    关键字:

天才代写-代写联系方式