首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++/CLI 深拷貝機制實戰:ICloneable 介面完整解析

     編輯:關於C++

前言:為何需要「克隆」?

C++/CLI 同時支援堆疊型與堆積型物件,但 C#、VB.NET 等 CLI 語言僅支援堆積型物件。在堆積環境中,物件存取永遠透過控制代碼(handle)。若要實現物件獨立副本,避免多個控制代碼指向同一實體造成非預期副作用,必須實作「深拷貝」機制——即「克隆」。

使用內建 Clone 方法

System::ArrayList 等集合類別已實作 ICloneable 介面:

ArrayList^ al1 = gcnew ArrayList;
al1->Add("Red"); al1->Add("Blue"); al1->Add("Green"); al1->Add("Yellow");
ArrayList^ al2 = static_cast(al1->Clone()); // 深拷貝

al1->Remove("Blue"); al1->Add("Black"); al1->RemoveAt(0); al1->Insert(0, "Brown");
// al1 變更不影響 al2,證明為深拷貝

淺拷貝(al2 = al1)僅複製參考,雙方指向相同元素集合;深拷貝則建立元素私有副本。

自訂類別實作 ICloneable

關鍵在於實作 System::ICloneable 介面,定義 virtual Object^ Clone() 方法:

public ref class Point : ICloneable
{
public:
    virtual Object^ Clone() { return MemberwiseClone(); }
};

Object::MemberwiseClone 建立新實例並複製所有欄位(淺拷貝)。對於值型別欄位(如 int),淺拷貝即滿足深拷貝需求。

包含參考型別欄位的深拷貝:Circle 範例

當類別包含參考型別欄位(如 Point^ origin)時,需手動深拷貝該欄位:

public ref class Circle : ICloneable
{
    Point^ origin; float radius;
public:
    virtual Object^ Clone() override
    {
        Circle^ c = static_cast(MemberwiseClone()); // 淺拷貝 Circle
        c->origin = static_cast(origin->Clone());    // 深拷貝 Point
        return c;
    }
};

測試程式證明:修改 c1 的 origin 不影響 c2。

陣列與泛型類別的克隆

所有 CLI 陣列繼承自 System::Array,已實作 ICloneable:

generic 
public ref class Vector
{
    array^ vector;
public:
    virtual Object^ Clone()
    {
        Vector^ v = static_cast^>(MemberwiseClone());
        v->vector = static_cast^>(vector->Clone()); // 含陣列符號轉型
        return v;
    }
};

繼承階層中的克隆鏈

衍生類別應呼叫基類 Clone() 而非 MemberwiseClone(),確保基類部分正確克隆:

public ref class Derived : Base, ICloneable
{
    virtual Object^ Clone() override
    {
        Derived^ d = static_cast(Base::Clone()); // 呼叫基類 Clone
        d->dPair = static_cast^>(dPair->Clone());
        return d;
    }
};

Clone 宣告為 virtual 確保多型呼叫正確性。

無建構函式的物件建立與靜態計數器

克隆不應呼叫建構函式。若類別有靜態計數器追蹤物件數量,需在 Clone 中手動遞增:

public ref class Test : ICloneable
{
    static int objectCount = 0;
    virtual Object^ Clone()
    {
        Test^ copy = static_cast(MemberwiseClone());
        ++objectCount; // 手動同步靜態計數
        return copy;
    }
};

輸出證明:建構與克隆皆正確遞增計數器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved