質問

通常、「使用」宣言は、他の方法では非表示になる基本クラスのいくつかのメンバー関数を範囲に持ち込むために使用されます。その観点からは、アクセス可能な情報をより便利にするためのメカニズムにすぎません。
ただし、「使用」宣言を使用して、アクセス制約を変更することもできます(関数だけでなく、属性についても)。例えば:

class C{
public:
  int a;
  void g(){ cout << "C:g()\n"; }
  C() : a(0){}
};

class D : public C{
private:
  using C::a;
  using C::g;
public:
  D() { a = 1; }
};

int main(void){
  D d;
  cout << d.a << endl;  //error: a is inaccessible
  C *cp = &d;
  cout << cp->a << endl; //works
  d.g();  //error: g is inaccessible
  cp->g();  //works
  return 0;
}

派生クラスでのこのアクセスのこの制限は、実際には役に立たないと思います。なぜなら、あなたは常にベースクラスにg()とaにアクセスできるためです。それでは、少なくともある種のコンパイラ警告があるべきではありませんか?それとも、派生したクラスによるアクセスのそのような制限を禁止する方がさらに良くなかったでしょうか?使用する宣言は、アクセスに制約を追加する可能性だけではありません。また、基本クラスの機能をオーバーライドすることで、アクセス制約を増やすセクションに配置することもできます。そのような方法でアクセスを制限することが実際にnessecaryである合理的な例はありますか?そうでない場合は、なぜ許可されるべきかわかりません。

そして別のこと:少なくともG ++では、同じコードが「使用」という言葉なしでよくコンパイルされます。つまり、上記の例を意味します。C:: Aを書くことが可能です。およびc :: g; c :: aを使用する代わりに; c :: gを使用しています。最初の唯一のショートカットは後者のショートカットですか、それとも微妙な違いがありますか?

//編集:
だから、私の結論以下の議論と回答から:
- 公開された派生クラスのアクセス制約を制限することが許可されています
- 使用できる便利な例があります
- それがテンプレートと組み合わせて問題を引き起こす可能性があります(たとえば、派生クラスは、ベースですが、これ以上一部のテンプレートクラス/関数の有効なパラメーターではありません)
- よりクリーンな言語のデザインはそのような使用を許可してはなりません
- コンパイラは少なくとも何らかの警告を発することができます

役に立ちましたか?

解決

あなたの宣言に関して using: :これらは「アクセス宣言」と呼ばれ、非推奨です。以下は、標準のテキストです 11.3/1:

基本クラスのメンバーのアクセスは、派生クラスのIDに言及することにより、派生クラスで変更することができます。そのような言及は、アクセス宣言と呼ばれます。アクセス宣言の効果 qualified-id; 宣言と同等であると定義されています usingqualified-id; 脚注:アクセス宣言は非推奨です。メンバー 使用を使用します (7.3.3)同じことをするためのより良い手段を提供します。 C ++言語の以前のバージョンでは、アクセス宣言はより制限されていました。それらは一般化され、同等になりました 使用を使用します - 終了脚注

ほとんどの場合、変更するのは良くないと思います 公衆 メンバーへ プライベート また 保護されています これは代替原則に違反するため、派生クラスのメンバー:基本クラスにはいくつかの機能があることを知っています。 予想 派生クラスのために、これらの機能も呼び出すことができます is-a ベース。そして、あなたがすでに述べたように、この不変は、基本クラスの参照に変換すること(暗黙的に動作します!)、または関数名の資格を取得し、(その後パブリック)関数を呼び出すことを可能にする言語によってすでに施行されています。

ベースの関数のセットを呼び出す人を禁止したい場合、このヒントは、封じ込め(またはまれな場合、私的継承)がより良いアイデアだと思います。

他のヒント

あなたが示した宣言を使用することは、アクセスレベルを変更するメカニズムを提供しますが(ただし、ダウンのみ)、それはそのようなコンテキストでの主要な使用ではありません。コンテキストを使用することは、主に言語メカニズムのために基本クラスから影がつかれる関数へのアクセスを許可することを目的としています。例えば

class A {
public:
   void A();
   void B();
};

class B {
public:
   using A::B;
   void B(int); //This would shadow A::B if not for a using declaration
};

宣言

using C::a

「a」をローカルネーミングスコープにもたらし、後で「a」を使用して「c :: a」をrefereすることができます。それ以来、「c :: a」と「a」は、「a」という名前のローカル変数を宣言しない限り、交換可能です。

宣言はアクセス権を変更しません。 「A」がプライベートではないという理由だけで、サブクラスで「A」にアクセスできます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top