2015-12-13 13 views
16

へのアクセス:C++ 03のようが、私はまだ私の心で遊んで、この単純なクラス、作られたプライベートネストされたクラスに

class A { 
private: 
    class B {}; 

public: 
    B getB() { 
     return B(); 
    }; 
}; 

を、このクラスは罰金コンパイル、ない見栄えの良い方法がちょうどありません左辺値にgetB()の結果を割り当てるために、その意味で:

A::B b = A().getB(); 

コンパイルされません。

template <typename T> 
struct HideType { 
    typedef T type; 
}; 

HideType<A::B>::type b = A().getB(); 

をしかし、これはA :: Bの左辺値の変数を取得するためのこの単純なタスクのために、ちょうどひどいです:

私はこの方法で、中間テンプレートを使用してそれを得ました。

これはC++ 11以降では真実ではなく、少なくともgccではそうではありません。

A::B b = A().getB(); 

しかし、これは有効です:このコードはまだ有効ではありません

auto b = A().getB(); 

は、この標準点で抜け穴はありますか?

+1

: http://stackoverflow.com/questions/13532784/why-can-i-use-auto-on-a-private-type – OMGtechy

+1

私は[ 'HideType :: b型を取得することはできません= .. .'](http://ideone.com/jwsXhG)コンパイルするには、どこでMCVEを表示できますか?代わりにlitbの[robber structure](http://stackoverflow.com/questions/15110526/allowing-access-to-private-members)に興味があるかもしれません。 –

答えて

1

A::B b = A().getB()が機能しないのは、BAのプライベートクラスメンバーであるためです。コードを公開すると、コードがコンパイルされます。 autoは、autoがオブジェクトのコンストラクタを呼び出す必要なく(declvalのように)オブジェクトに割り当てられたオブジェクトの型をチェックするだけなので、autoで動作します。したがってには返品タイプgetBが割り当てられ、クラスAにあります。あなたも、次のようにコードを変更することができます。

decltype(declval<A>().getB()) b = A().getB(); 

declvalはあなたに新しいものであるならば、私はそれが機能の戻り値の型の右辺値を返すことを教えなければなりません(ここでは戻り値の型があるgetB (これはdecltypesizeofのような関数でのみ使用するべきです)。クラスオブジェクトの作成とその関数の使用によるオーバーヘッドを防ぎます。

今私によれば、これは標準の抜け穴ではないと私はループを感じる穴が取り除かれました!あなた自身のコードから明らかです。関数getBを参照してください。 Bのオブジェクトをインスタンス化することは、それがプライベートで定義されているので難しいです!このような場合、Bでの作業は困難になります。この背後にある考え方は、クラスAのタイプ(すなわちB)の名​​前にアクセスできないが、そのタイプはまだ使用可能であるため、Bのオブジェクトを得ることができるのです。このテンプレートのコードを理解している場合は、autoの使用を理解することができます: -

#include <iostream> 
#include <type_traits> // for std::is_same 
using namespace std; 
class A 
{ 
    class B 
    {}; 
    public: 
    B getB() 
    { 
     return B(); 
    } 
}; 
template<typename T> 
void check (T b) 
{ 
    cout<<boolalpha; 
    is_same<decltype(declval<A>().getB()), T> x; // checks if T & B are of same type 
    cout<<x.value<<'\n'; 
} 
int main() 
{ 
    A obj; 
    check (obj.getB()); 
    return 0; 
} 

出力: -

true 

templateが故にautoBを識別できるので、あまりにもBを識別します。規格から

+0

"*これは' auto'と同じ働きをします! 'auto'は!!!!それが割り当てられた型が有効かどうかをチェックします*"これはすべて不器用です。 – ildjarn

+0

'decltype'は' auto'と同じようにC++ 11なので、それを推薦する際のポイントは何ですか? –

+0

OPに 'auto'を使わなくても' B'のオブジェクトにアクセスできることを伝えるための追加情報があります。 – Anwesha

9

、条項11(メンバーアクセス制御):

クラスのメンバーであることができる
- プライベート。つまり、そのの名前は、それが宣言されているクラスのメンバーおよびフレンドによってのみ使用できます。
- 保護されています。つまり、そのの名前は、それが と宣言されたクラスのメンバーおよびフレンド、そのクラスから派生したクラス、およびその友人によってのみ使用できます(11.4を参照)。
- public;つまり、の名前は、アクセス制限なしでどこでも使用できます。

にアクセス制御が適用されます。

auto b = A().getB(); 

であなたがプライベートの名前を使用していない、したがって、それは標準

それはそう
0

によると、法的です、そこに標準のドラフトではこのような欠陥だったが、それはされていましたWP 1170によって修正されました。

おそらく、コンパイラのバグがあります。 auto b = A().getB();の宣言には、auto型指定子のテンプレート引数の差し引きが含まれているため、C++ 11標準によれば、型減算が失敗するため、不正な形式にする必要があります。

関連
関連する問題