科技时代新浪首页 > 科技时代 > 学园 > 正文

实例解析C++/CLI的克隆(2)


http://www.sina.com.cn 2006年09月11日 09:01 天极yesky

  克隆数组

  请看例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

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

[上一页] [1] [2]

本文导航:
·实例解析C++/CLI的克隆
·实例解析C++/CLI的克隆(2)

发表评论

爱问(iAsk.com)



评论】【论坛】【收藏此页】【 】【多种方式看新闻】【下载点点通】【打印】【关闭




科技时代意见反馈留言板 电话:010-82628888-5595   欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

Copyright © 1996 - 2006 SINA Inc. All Rights Reserved

新浪公司 版权所有