Entry

プログラミングメモ - boost::noncopyable について少し

2009年03月27日

boost::noncopyable は,コピー不可なクラスを宣言するために使う便利クラスです。C++ の場合,クラスを宣言すると,コピーコンストラクタと代入演算子が自動的に定義されてしまうので,コピーを許さないクラスを作るには,これらを private で宣言しておく必要があります。こんな感じで。

class Foo {
public:
  Foo();
  virtual ~Foo();
private:
  Foo(const Foo& other);
  Foo& operator=(const Foo& rhs);
public:
  // some operations and members ...
};

private で宣言しておいて定義はしないから,コピーするコードを書くと,そこでコンパイルエラーが出ます。これで,不正なコピーを検知できるというわけ。で,この仕組みを使ったのが,boost::noncopyable。上のようなクラスを親として継承することで,子クラスでコピーコンストラクタや代入演算子を定義しなくても,エラーを検知できるというわけです。

で,この方法なんですけれど,やり方としてまっとうなんだろうかとつらつら。C++ は多重継承を許しているから,実質的にはあまり影響はないと思うんですけれど,クラスの継承関係に変な機能を持ち込んでいるような気がする。

この点,例えば,Google のやり方では,DISALLOW_COPY_AND_ASSIGN マクロを使うことにしているようです。あたしも,最近このやり方を使おうかと思っていて,実際いくつかのソースで使っている。

// A macro to disallow the copy constructor and operator= functions 
// This should be used in the private: declarations for a class 
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  TypeName(const TypeName&); \ 
  void operator=(const TypeName&) 

Then, in class Foo:

class Foo { 
public: 
  Foo(int f); 
  ~Foo(); 
private:
  DISALLOW_COPY_AND_ASSIGN(Foo); 
};
Google C++ Style Guide

マクロ展開すると,冒頭 Foo と同じ宣言になります。もっとも,上のやり方そのままだと,public に宣言したら意味がなくなってしまいます。んなもんで,あたしのは private も含めてマクロ定義しています。けど,やってることは同じようなもの。ともかく,この方法だと,継承関係を汚染しません。

一方,この方法の欠点はというと,C++ 使いが忌み嫌うマクロを使っていることです。もちろん,これでもコンパイルエラーはたしかに出るんですけれど,マクロ展開された後のメッセージなので,場合によっては意味不明なメッセージが出て,混乱することがあるかもしれません。MFC のシリアライズ周りでも,似たようなマクロ定義をクラス宣言や定義に含めるお約束になっているんですけれど,なんつか,プリプロセッサに頼るっつこと自体,プログラミングスタイルとしてあまりかっこよくありません。

なんか,普通に private 宣言すればいいだけのような気もしてきた。少し手間だけど,

private:  // no implement
  Foo(const Foo& other);
  Foo& operator=(const Foo& rhs);

って書いとけば,意味的にも分かりやすいし。どうなんだろ。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN