[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 のコピー
}
[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 のコピー
}
▼ スレッド
- 789: 市川@vivi-vine.org です X のメンバ member_obj の扱い方法として、ポインタのままコピーする 浅いコ Shin'ichi Ichikawa
- ├790: シリアライズを実装し、テキトーなファイルに書いて、読み戻す。 …違うな。これはcloneの実 FUKUDA, Fumiki
- │└794: 市川@vivi-vine.org です うーむ、言語レベルで浅いコピーしかサポートしていないのは、 C から変 Shin'ichi Ichikawa
- └800: へんてこりんなテンプレートを考えてみました。 スマートポインタの一種ですが、クラスのデ mori_mi‐at‐itg.hitachi.co.jp
- └809: 市川@vivi-vine.org です NULL で初期化したい場合は、Null クラスを作るという方法で逃げられるかな Shin'ichi Ichikawa
- └819: はい。やはり Null であるインスタンスを作成するデフォルトコンストラクタ を追加すべきかも mori_mi‐at‐itg.hitachi.co.jp
- └824: 市川@vivi-vine.org です 時間が取れなかったのと重なりまして... Null が表現できるようになったの Shin'ichi Ichikawa