ssacontents

C++において、オブジェクトのスライシングとは、

class base {
   int a;
   virtual const char* name() { return "base"; }
}; 
class sub : public base {
   int b;
   virtual const char* name() { return "sub"; }
};

void hoge(base& b) {
    printf("%s\n", b.name());
    base tmp = b; 
    printf("%s\n", tmp.name());
}
 
sub s;
hoge(s);
...

hoge()では、"sub","base"が表示される。
文法的には正しいので、警告はでない。このミスを見つけるのは困難。

これを未然に防ぐには、工数がかかるけど以下のようにする。

class base {
   int a;
   base() : a(0) {}
   base(const base& b) : a(b.a) {}
   virtual ~base() {}
   virtual const char* name() { return "base"; }
   virtual base* clone() { return new base(*this); }
   static void destroy(base* b) { delete b; }
private:
   void operator = (const base&);
}; 
class sub : public base {
   int b;
   sub() : b(0) {}
   sub(const sub& s) : base(s), b(s.b) {}
   virtual ~sub() {}
   virtual const char* name() { return "sub"; }
   virtual base* clone() { return new sub(*this); }
};

void hoge(base& b) {
    printf("%s\n", b.name());
    base* tmp = b->clone(); // base tmp = b;ではビルドエラー 
    printf("%s\n", tmp->name());
    base::destroy(tmp); // baseとしてdeleteされるので仮想デストラクタ必須
} 
 
sub s;
hoge(s);
...

hoge()では、"sub","sub"が表示される。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-06-07 (火) 21:27:15 (2626d)