2012-03-28 7 views
6

私が元々望んでいたことは、おそらくC++ 11が関与していない可能性があることが判明した後に、要件を少し変更して、 。コンパイル時にベースクラスが "interface"であるかどうかを確認する

previous question

基本的に私はクラスが「インターフェース」から継承している場合は、コンパイル時にチェックしたいです。インターフェイスでは、純粋な仮想メソッドのみでクラスを意味します。 私は、次のコードを実行したい:Tは純粋仮想メソッドのみ、それがコンパイルされ、その方法の一つが、その後失敗していない場合がある場合は、ここに

template <typename T> 
class Impl : public T { 
public: 
STATIC_ASSERT_INTERFACE(T); 
}; 

動作です。

誰もがそのようなことを考えることができますか?

+1

本当にすべてのメソッドは純粋な仮想ですか?デストラクタ? – Andrzej

+0

おそらく 'T 'にも基本クラスがあるかどうかをチェックし、そうであればそれらも"インタフェース "かどうかをチェックしたいと思うでしょう。しかし答えは確かに "いいえ"です。 – MSalters

答えて

2

これは基本的にJavaインターフェイスに似ています。 C++では、interfaceの存在はありません。それは、すべての純粋仮想メソッドとstatic constデータメンバーだけのclassで使用される単なる用語です。

さらに、純粋な仮想メソッドには関数本体がある場合とない場合があります。したがって、C++の純粋仮想メソッドは、Javaの抽象メソッドとまったく同じではありません。

残念ながら、は、をC++でシミュレートすることはお勧めできません。

+0

基本的には、すべてのメソッドを仮想化して、それらをオーバーライドするようにしたいと思います(私はc'torなどについて話していません)。 –

+0

@ VadimS:すべてのメソッドをオーバーライドするか、ベースクラスのメソッドをオーバーライドするはずのメソッドを記述する際に、実際にどうしたらよいか確認したいのですか? –

+0

私は(コンパイル時に)基本クラスのメソッドをオーバーライドしたいが、そのメソッドが '仮想'として定義されていない場合を避けたい。 –

1

まず、インターフェイスはC++のネイティブな概念ではありません。私は、ほとんどのプログラマーが自分たちが何であるかを知っていると確信していますが、コンパイラーはそうではありません。 C++はたくさんのことをすることができます。あなたはそれをさまざまな言語のように見せることができますが、C++を書くつもりなら、C++のやり方をするのが最善です。

もう1つのこと - ここには多くの灰色の領域があります。あなたが示唆したように、あなたが「インターフェース」を持っていたが、誰かがこれらのいずれかをした場合:

// Technically not a member function, but still changes the behavior of that class. 
bool operator==(const Interface &left, const Interface &right); 

私はあなたがそれをやってから誰かを停止することはできませんほぼ100%確信しています。

メンバー変数が存在しないことを確認することができますが、私はこのようなことに同意できないかもしれません。空のクラスを作成し、static_assert(sizeof(InterfaceClass) == sizeof(Empty))を実行します。サイズが0であると想定するのが安全かどうかはわかりません。これは、標準に精通している人にとっては疑問です。

+1

これは決して0にはなりません。もし 'Empty'型の複数の変数を宣言すると、それぞれの変数はメモリ内に一意のアドレスを持たなければなりません。 – enobayram

+1

'static_assert(sizeof(InterfaceClass)== sizeof(Empty))' - 確かではありません。 sizeと空のクラス(メンバ変数も仮想関数もない)は1バイトになり、 'InterfaceClass'のサイズは通常1バイトにはならず、おそらく仮想関数は4バイトのサイズになりますポインタ) – Sanish

1

あなたが望むものは、他の人が既に説明したように、直接行うことはできません。

しかし、インターフェイス開発者からの訓練を受けても、必要な動作を引き続き得ることができます。すべてのインターフェイスが共通の基底クラスInterfaceから派生している場合は、this questionに似たテクニックを使用して、コンパイル時にInterfaceが基本クラスであることを確認できます。例えば

:もちろん

class Interface { 
    public : 
     virtual ~Interface() { } 
}; 

template <typename T> 
struct IsDerivedFromInterface { 
    static T t(); 
    static char check(const Interface&); 
    static char (&check(...))[2]; 
    enum { valid = (sizeof(check(t())) == 1) }; 
}; 

class MyInterface : public Interface { 
    public : 
     virtual void foo() = 0; 
}; 

class MyBase { 
    public : 
     virtual void bar() { } 
}; 

class Foo : public MyInterface { 
    public : 
     virtual void foo() { } 
}; 
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Foo>::valid); // just fine 

class Bar : public MyBase { 
    public : 
     virtual void bar() { } 
}; 
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Bar>::valid); // oops 

、基本クラスの開発者は、基本クラスがインターフェイスでなくてもInterfaceからカンニングと導出することができます。だから私はそれが開発者からいくつかの規律を必要としていると言いました。

しかし、私はこれがどのように役立つかはわかりません。この種のコンパイル時間チェックが必要なことは一度も感じていません。

関連する問題