11

通常、「using」宣言は、そうでなければ隠される基底クラスの一部のメンバー関数をスコープに入れるために使用されます。その観点からは、アクセス可能な情報をより便利に使用するためのメカニズムにすぎません。
ただし、'using' 宣言を使用して、アクセス制約を変更することもできます (関数だけでなく、属性に対しても)。例えば:

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 にアクセスできるため、派生クラスでのこのアクセス制限は実際には役に立たないと思います。では、少なくとも何らかのコンパイラ警告が表示されるべきではないでしょうか? それとも、派生クラスによるアクセスの制限を禁止する方がよいのではないでしょうか? using 宣言は、アクセスに制約を追加する唯一の可能性ではありません。また、基本クラスの関数をオーバーライドして、より多くのアクセス制限を持つセクションに配置することによっても実行できます。そのような方法でアクセスを制限することが本当に必要な合理的な例はありますか? そうでない場合、なぜそれを許可する必要があるのか​​ わかりません。

もう 1 つ: 少なくとも g++ では、同じコードは「using」という単語がなくても適切にコンパイルされます。つまり、上記の例では、C::a; と書くことができます。および C::g; C::a; を使用する代わりに C::g を使用して; 最初のものは後者の近道にすぎないのでしょうか、それとも微妙な違いがありますか?

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

4

3 に答える 3

5

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

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

ほとんどの場合、派生クラスでパブリックメンバーをプライベートまたはプロテクトメンバーに変更するのは良くありません。これは、置換の原則に違反するためです。基本クラスにはいくつかの関数があることがわかっています。派生クラスベースであるため、これらの関数も呼び出し可能であると考えてください。そして、すでに述べたように、この不変条件は言語によってすでに強制されており、基本クラス参照に変換したり (暗黙的に機能します!)、関数名を修飾したり、(次に public) 関数を呼び出したりすることができます。

If you want to forbid someone calling a set of functions of the base, then i think this hints that containment (or in rare cases, private inheritance) is a better idea.

于 2010-01-18T09:30:42.320 に答える
3

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

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
};
于 2010-01-18T09:01:38.270 に答える
0

宣言

using C::a

"a" をローカルの名前付けスコープに持ち込んで、後で "a" を使用して "C::a" を参照できるようにします。そのため、「a」という名前のローカル変数を宣言しない限り、「C::a」と「a」は交換可能です。

宣言はアクセス権を変更しません。「a」はプライベートではないため、サブクラスの「a」にのみアクセスできます。

于 2010-01-18T08:59:40.520 に答える