1
class safe_bool_base { 
protected: 
    void this_type_does_not_support_comparisons() const {} 
}; 

template <typename T=void> class safe_bool : public safe_bool_base { 
public: 
    void func() { 
    &safe_bool::this_type_does_not_support_comparisons; 
    &safe_bool_base::this_type_does_not_support_comparisons; 
    } 
}; 

template<> class safe_bool<void> : public safe_bool_base { 
public: 
    void func() { 
    &safe_bool::this_type_does_not_support_comparisons; 
    &safe_bool_base::this_type_does_not_support_comparisons; 
    } 
}; 

エラーメッセージ:保護されたメンバーアクセスエラー

zzz.cpp: In member function 'void safe_bool<void>::func()': 
zzz.cpp:7:10: error: 'void safe_bool_base::this_type_does_not_support_comparison 
s() const' is protected 
void this_type_does_not_support_comparisons() const {} 
    ^
zzz.cpp:22:24: error: within this context 
    &safe_bool_base::this_type_does_not_support_comparisons; 
        ^

保護されたメンバーは、テンプレートの特殊化で訪問することができない私はなぜだろうか。コードは無意味で、テストのためだけです。

+1

実際、 'safe_bool_base :: this_type_does_not_support_comparisons()'はうまくいきますが、 '&safe_bool_base :: this_type_does_not_support_comparisons'(関数のアドレスを取る)は機能しません。だから私は問題を理解したい。 – immiao

答えて

1

パブリッククラスの継承元が基本クラスである場合、その保護されたメンバーは派生クラス '派生クラスのメンバー関数でアクセスできるメンバーを保護します。それらは、派生クラス自体(およびその派生クラス)を介してのみアクセスされることに注意してください。ただし、保護されたメンバーには基本クラスからアクセスできません。なぜ&safe_bool::this_type_does_not_support_comparisons;が動作するのですか?&safe_bool_base::this_type_does_not_support_comparisons;です。規格から

$11.4/1 Protected member access [class.protected]

(emphasie鉱山)

場合、非静的データメンバ以前句 に記載されたもの[class.access]を超えて追加のアクセスチェックが適用され非静的 メンバ関数は、その名前付けクラスの保護されたメンバです ([class.access.base])114先に説明したように、参照は友人またはメンバで発生するため、 のあるクラスC. アクセスがメンバ ([expr.unary.op])へのポインタを形成する場合、ネストされた名前指定子は、CまたはCから派生したクラス を表すものとする。その他のアクセスはすべて、(おそらく暗黙の) オブジェクト式([expr.ref])。

注サンプルコード内のステートメントint B::* pmi_B = &B::i; // ill-formedから - [エンド例えば

class B { 
protected: 
    int i; 
    static int j; 
}; 

class D1 : public B { 
}; 

class D2 : public B { 
    friend void fr(B*,D1*,D2*); 
    void mem(B*,D1*); 
}; 

... 
void D2::mem(B* pb, D1* p1) { 
    pb->i = 1;     // ill-formed 
    p1->i = 2;     // ill-formed 
    i = 3;      // OK (access through this) 
    B::i = 4;      // OK (access through this, qualification ignored) 
    int B::* pmi_B = &B::i;  // ill-formed 
    int B::* pmi_B2 = &D2::i;  // OK 
    j = 5;      // OK (because j refers to static member) 
    B::j = 6;      // OK (because B::j refers to static member) 
} 

... 

例]この場合、オブジェクト 発現のクラスは、CまたはCから派生したクラスでなければなりません標準、基本的にはコードの場合と同じです。それはテンプレート専門とは関係ありません。

+0

まあ、コンパイラはテンプレート宣言ではなく、特殊化を報告します。テンプレートの専門化を考えさせてしまった。あなたの詳細な説明をありがとう! – immiao

関連する問題