[cppll_novice:0800] Re: 派生オブジェクトのコピー

Subject:
[cppll_novice:0800] Re: 派生オブジェクトのコピー
From:
mori_mi‐at‐itg.hitachi.co.jp <mori_mi@...>
Date:
Mon, 24 Jan 2005 17:24:03 +0900 (JST)
X-Mailer:
FreeML Web Mailer XP; SP2
Message-Id:
<4757075.1106555043507‐at‐www1.local.freeml.net>
In-Reply-To:
789
References:
789
森です。

[cppll_novice:0789] 送信者 : chan@..., 受信日 :2005/01/22
12:42
>深いコピーをする場合に、
>A と B に自分自身をコピーしたものを返す clone 関数を
>追加するという方法以外に、member_obj をコピーする方法が
>提案できる方、よろしくお願いします

へんてこりんなテンプレートを考えてみました。
スマートポインタの一種ですが、クラスのデータメンバのポインタの代替品で
あり、ポインタのコピー時にポイントしているオブジェクトを複製するもので
す。またオリジナル作成時に静的型とは別に、動的型を指定する必要がありま
すが、コピーは動的型で行われます。デストラクトは静的型ですが、仮想デス
トラクタがあれば問題ありません。

技術的には、動的型のコピーコンストラクタをラップした関数テンプレートを
実体化し、本スマートポインタはその関数実体へのポインタを保持しています。
ポイントしているオブジェクトは必ず異なるものなので、所有権/参照カウン
トは必要ありません。またマルチスレッドのことなど全く考慮していません。

使い方は、以下の通りです。ろくにテストしていないのでバグはたくさんある
と思います。

class Foo {...};
class Bar: public Foo {...};
Clone<Foo> boo(new Bar);  // オリジナルの定義 静的型 Foo, 動的型 Bar
Clone<Foo> poo(boo);      // poo は boo のコピー
Foo* p = boo.get();       // 生ポインタ
Foo* q = poo.get();       // p != q, p も q も動的型は Bar

// -------------------------------------------------------
// テンプレートのコード

template<typename Base> class Clone {
   template<typename Delivered> struct Overload {
       static void* Copy(void* origin) {
           return static_cast<void*>(new Delivered
(*reinterpret_cast<Delivered*>(origin)));
       }
   };
   void* (*copy)(void* origin);
   void* object;
   Base* base;
public:
   template<typename Delivered> explicit Clone(Delivered* pointer) {
       static Overload<Delivered> overload;
       copy = &overload.Copy;
       object = static_cast<void*>(pointer);
       base = dynamic_cast<Base*>(pointer);
   }
   Clone(const Clone<Base>& origin) {
       copy = origin.copy;
       object = copy(origin.object);
   }
   ~Clone() {
       delete reinterpret_cast<Base*>(object);
   }
   Base* get() { return base; }
   void* top() { return object; }
};

// -------------------------------------------------------
// 以下テンプレートをテストするためのコード

#include <stdio.h>

struct Foo {
   Foo() { printf("Foo constructor, this = %p\n", this); }
   Foo(const Foo& foo) { printf("Foo copy constructor(%p), this = %
p\n", &foo, this); }
   virtual ~Foo() { printf("Foo destructor, this = %p\n", this); }
   typedef Foo Type;
};

struct Bar: public Foo {
   Bar() { printf("Bar constructor, this = %p\n", this); }
   Bar(const Bar& bar): Foo(bar) { printf("Bar copy constructor(%p),
this = %p\n", &bar, this); }
   virtual ~Bar() { printf("Bar destructor, this = %p\n", this); }
   typedef Bar Type;
};

struct Pom {
   Clone<Foo> foo;
   Pom(const Clone<Foo>& poo): foo(poo) {
       printf("Pom constructor, this = %p, foo = %p\n", this, foo.get
());
   }
   Pom(const Pom& pom): foo(pom.foo) {
       printf("Pom copy constructor(%p), this = %p, foo = %p\n", &pom,
this, foo.get());
   }
   ~Pom() {
       printf("Pom destructor, this = %p, foo = %p\n", this, foo.get
());
   }
};

void main() {
   Clone<Foo> boo(new Bar);  // オリジナルは動的型を明示要という制限あり
   Pom pom(boo);    // pom.foo は boo のコピー
   puts("TEST");
   Pom copy(pom);   // copy.foo は pom.foo のコピー
}

スレッド

Navigation

検索

[検索ヘルプ]

Maintener: Tietew <www.tietew.jp>
Powered by Ruby on Rails, Mongrel, PostgreSQL, and Hyper Estraier.
click here