2013-06-06 12 views
9

を保護されて、私は次のコードはコンパイルされません理由を知りたい:C++エラー:基本機能は

class base { 
protected: 
    typedef void (base::*function_type)() const; 
    void function_impl() const {} // error: ‘void base::function_impl() const’ is protected 
}; 

class derived: public base { 
public: 
    operator function_type() const { 
    return boolean_test() == true ? &base::function_impl : 0; // error: within this context 
    } 

protected: 
    virtual bool boolean_test() const = 0; 
    virtual ~derived() {} 
}; 

int main(int argc, char* argv[]) { 
} 

g++出力:

~/protected_test$ g++ src/protected_test.cpp 
src/protected_test.cpp: In member function ‘derived::operator base::function_type() const’: 
src/protected_test.cpp:4:8: error: ‘void base::function_impl() const’ is protected 
src/protected_test.cpp:10:44: error: within this context 

このコードはhereから適応していないと私は何を見ました1つはディスカッションフォーラムでそれについて不平を言う。また、私はg ++ 4.7.2を使用しています。同じコードをコンパイルし、egcs-2.91.66とうまくリンクします。

+0

いずれかのコンパイラがバグか、またはどちらか一方がバグです。 :D – Wug

答えて

10

保護アクセスの仕様では、派生型(つまりderived::...)またはそれから継承された型のいずれかでメンバーへのポインタを形成する必要があると記載されています。 function_implの名前はbaseで直接指定することはできません。あなたのケースでは、あなたがアドレスを取得するために&derived::function_impl表現を使用している場合でも、結果の型は名前function_implであるため、まだvoid (base::*function_type)() constであること

operator function_type() const { 
    return boolean_test() == true ? &derived::function_impl : 0; 
} 

注意として、それをしなければならないことを意味

この場合、baseクラスの機能に解決されます。

特定のコンパイラ(またはその特定のバージョン)でコンパイルすると、そのコンパイラがエラーを通過させることができただけで、リンクのコードがわかります。

+1

+1。関連する段落は11.4/1です。 –

+1

私は結果の型に同意しません - あなたが記述した振る舞いは型セーフではありません。(あなたが間違っているかC++標準であるかわかりません)これは 'dynamic_cast (o)'が合法ではないと思われる場合でも、 'Derived'メンバー関数が' o.function_impl() 'を間接的に呼び出すことを可能にする抜け穴を作り出します。 –

+0

これは、C++標準の例が壊れているようです。 –