科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件实例解析C++/CLI的“克隆”

实例解析C++/CLI的“克隆”

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

C++/CLI不但支持基于堆栈的对象,同时也支持基于堆的对象。

作者:谢启东编译 来源:天极开发 2007年11月14日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
 克隆数组

  请看例5,其扩展了泛型类Vector以支持克隆。因为所有的CLI数组类型均派生自System::Array,而其也实现了System::ICloneable接口,所以可以对一个数组的引用,简单地调用Clone以复制数组中的元素,如例子中所示。当然,在转换中也必须包括数组符号。

  例5:

generic <typename T>
public ref class Vector
{
 int length;
 /*1*/ array<T>^ vector;

 public:
  virtual Object^ Clone()
  {
   Vector<T>^ v = static_cast<Vector<T>^>(MemberwiseClone());
   v->vector = static_cast<array<T>^>(vector->Clone());
   return v;
  }

};

int main()
{
 /*1*/ Vector<int>^ v1 = gcnew Vector<int>(5, 7);
 /*2*/ Console::WriteLine("v1: {0}", v1);
 /*3*/ Vector<int>^ v2 = static_cast<Vector<int>^>(v1->Clone());
 /*4*/ Console::WriteLine("v2: {0}", v2);
 /*5*/ v1[0] = 3;
 /*6*/ v1[3] = 9;
 /*7*/ v2[4] = 1;
 /*8*/ Console::WriteLine("v1: {0}", v1);
 /*9*/ Console::WriteLine("v2: {0}", v2);
}

  克隆并派生类

  到目前为止,所演示的方法对直接从Object^派生而来的类来说,都完全正确,然而,对从其他类派生而来的类来说,就不正确了。请看例6,因为是直接从System::Object派生而来,所以它的克隆方法正如前面所看到的那样。Base被用作基类,而例7中的程序由其派生而来:

  例6:

public ref class Base : ICloneable
{
 array<int>^ bPair ;
 public:
  Base(int i, int j)
  {
   bPair = gcnew array<int>(2) {i, j};
  }
  void SetValue(int i, int j)
  {
   bPair[0] = i;
   bPair[1] = j;
  }
  virtual String^ ToString() override
  {
   return String::Concat("[", bPair[0], ":", bPair[1], "]");
  }
  virtual Object^ Clone() override
  {
   Base^ b = static_cast<Base^>(MemberwiseClone());
   b->bPair = static_cast<array<int>^>(bPair->Clone());
   return b;
  }
};

  例7:

using namespace System;

public ref class Derived : Base, ICloneable
{
 array<int>^ dPair;
 public:
  Derived(int bi, int bj, int i, int j) : Base(bi, bj)
  {
   dPair = gcnew array<int>(2) {i, j};
  }
  void SetValue(int bi, int bj, int i, int j)
  {
   Base::SetValue(bi, bj);
   dPair[0] = i;
   dPair[1] = j;
  }
  virtual String^ ToString() override
  {
   return String::Concat("[{", Base::ToString(), "}", dPair[0], ":", dPair[1], "]");
  }
  virtual Object^ Clone() override
  {
   // Derived^ d = static_cast<Derived^>(Base::MemberwiseClone());
   Derived^ d = static_cast<Derived^>(Base::Clone());
   d->dPair = static_cast<array<int>^>(dPair->Clone());
   return d;
  }
};

  在Derived中显示声明实现ICloneable是多余的,因为Derived的基类已经这样做了。而这个例子中唯一新的东西就是在Clone中调用Base::Clone,这取代了前一个对MemberwiseClone的调用(其已被注释)。通过调用Base::Clone(其会调用基类的Clone,而它又最终调用Object::MemberwiseClone),这做就得到了一个基类对象的克隆。例8是测试程序。

  例8:

int main()
{
 Derived^ d1 = gcnew Derived(10, 20, 30, 40);
 Console::WriteLine("d1 = {0}", d1);

 Derived^ d2 = static_cast<Derived^>(d1->Clone());
 Console::WriteLine("d2 = {0}", d2);

 d1->Base::SetValue(5, 6);

 Console::WriteLine("d1 = {0}", d1);
 Console::WriteLine("d2 = {0}", d2);
}

  在此,为什么要让Clone成为一个虚拟函数呢?因为,当调用Base::Clone时,必须确保调用了最恰当的实现,而虚拟函数查找,正是实现此的良方。

  无构造的创建

  一个对Clone的实现,不应调用任何其自身的类构造函数,对大多数类而言,这都不是问题,因为所有它们的构造函数只是初始化非静态的数据成员,然而,如果一个构造函数初始化了任意的静态数据成员或执行了其他的操作,这些操作在克隆期间就不会被完成,除非Clone本身执行了这些操作。在例9中,类Test包含了一个静态计数器,其跟踪类型对象被创建的数目;标记1与2执行了与构造函数同样的操作。

  例9:

public ref class Test : ICloneable
{
 int data;
 static int objectCount = 0;
 public:
  Test()
  {
   data = 0;
   ++objectCount;
  }
  Test(int value)
  {
   data = value;
   ++objectCount;
  }
  virtual String^ ToString() override
  {
   return String::Concat(data, ", ", objectCount);
  }
  virtual Object^ Clone()
  {
   /*1*/ Test^ copy = static_cast<Test^>(MemberwiseClone());
   /*2*/ ++objectCount;
   return copy;
  }
};
int main()
{
 /*3*/ Test^ t1 = gcnew Test;
 Console::WriteLine("t1 using new: {0}", t1);
 /*4*/ Test^ t2 = static_cast<Test^>(t1->Clone());
 Console::WriteLine("t2 using Clone: {0}", t2);
 /*5*/ Test^ t3 = gcnew Test(1);
 Console::WriteLine("t3 using new: {0}", t3);
 /*6*/ Test^ t4 = static_cast<Test^>(t3->Clone());
 Console::WriteLine("t4 using Clone: {0}", t4);
}
}

  以下是程序输出:

t1 using new: 0, 1
t2 using Clone: 0, 2
t3 using new: 1, 3
t4 using Clone: 1, 4

  由输出可见,当一个对象被构造或被克隆时,对象计数都相应地增长了。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章