2010-11-20 6 views
2

「不純な仮想関数」とは、診断目的で(http://www.gotw.ca/gotw/031.htmに記載されているような)実装も持つ純粋な仮想関数を意味します。これは不正な仮想関数を実装する正当な方法ですか?

それらを実装するためのコーシャ方法を行うことです。

class Foo 
{ 
public: 
    ... 
    virtual void Bar() = 0; 
}; 

void Foo::Bar() { assert(false); } 

しかし、これは、特にクラスの、一種の退屈では純粋仮想メソッドの数を持っています。また、対応する実装を追加することなく、誰かが誤って新しい純粋仮想関数を追加しないようにすることは難しいです。

理想的には私が何をしたいのですが、何がある:

class Foo 
{ 
public: 
    ... 
    virtual void Bar() = 0 
    { 
     assert(false); 
    } 
}; 

が、C++標準では、明示的にこの(ISO C++ 2003規格におけるセクション10.4/2)を禁止します。

代わりに、私は次のハックを考えました。 Foo.hヘッダで:

#ifndef ABSTRACT_METHOD 
#define ABSTRACT_METHOD = 0 
#endif 

class Foo 
{ 
public: 
    ... 
    virtual void Bar() ABSTRACT_METHOD; 
}; 

と、対応するFoo.cppソースファイルに:

#define ABSTRACT_METHOD { assert(false); } 

#include "Foo.h" 

... 

それは単一のコンパイルされた実装を取得するようになっています。

これは法的なのでしょうか?

+0

ソースファイルに ';'という疑いがあります。 –

+0

@Oli Charlesworth:Trueですが、何か本質的に間違っていますか?とにかく後続する ';'の責任をマクロ定義に移すことで、これは簡単に回避できます。 – jamesdlin

+1

@james:はい、私はそれがコンパイラエラーであると信じています。私はそれが自明に修正可能だと知っていますが、これは偶発的な観察であり、批判ではありません。 –

答えて

4

いいえ、合法ではありません。 1つの定義ルールでは、あるクラスが(異なる翻訳単位の)プログラム内に複数の定義を持つことができますが、それらの定義はすべて同じシーケンスのトークン(3.2/5)で構成されている必要があります。 ABSTRACT_METHODは(マクロ置換の前に)前処理トークンですが、それは十分ではありません。

したがって、.cppファイルは、ヘッダーを含む別の.cppと同じプログラムで有効に使用できません。

+1

ダーン、それは私が恐れていたものです。標準の該当するセクションを私に指摘してくれてありがとう。私は、 '__declspec(dllimport)'と '__declspec(dllexport)'属性が技術的に標準的な観点から合法ではないということを意味します。 – jamesdlin

+1

@jamesdlin:技術的にはそうですが、 '__declspec'は予約された名前なので、標準を含んでいるプログラムが厳密に準拠していないことに関係しています。プログラムは、Microsoftによって定義されたC++の方言でも有効ですが、ODR(明示的または暗黙的に)を緩和するドキュメントであれば問題ありません。 –

+0

おそらく、中間のビルドは、 'ABSTRACT_METHOD'を内部開発ビルドで異なるものにすることです(コンパイラが不完全な派生クラスをキャッチできるようにする)が、他の場所のスタブインプリメンテーションにすることでしょう。 – jamesdlin

0

有効かどうかはわかりません。しかし、クラスのユーザーがソースファイル内の派生クラスを宣言した場合、コンパイラは派生クラスにBar()を実装する必要がありません(= 0が表示されないため)。私はこれだけでこのようなことをしない理由になると思います。

+0

それは公正な点です。私たちは通常、クラスを別々のファイルに分けるので、私たちのコードベースの問題ではありません。もう1つのアプローチは、マクロの実装バージョンを定義し、様々な抽象基本クラスヘッダを含み、それ以外は何もしない単一の別個のソース 'impureVirtualStubs.cpp'ファイルを持つことです。 – jamesdlin

関連する問題