#include <iostream>
class Base
{
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingProtected(); // This does not compile
somethingProtected(); // But this is fine
}
};
int main()
{
Derived d;
d.somethingDerived();
return 0;
}
this
の保護されたメンバーのみが使用でき、他のインスタンスの保護されたメンバーには永遠に到達できないと思いました。
しかし:
class Derived : public Base
{
public:
void somethingDerived(Derived& d)
{
d.somethingProtected(); // This compiles even though d is
// potentially a different instance
}
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
}
};
私はこれまでしばらくC++でプログラミングを行ってきたので、これにはちょっと吐き気がしますが、この振る舞いの説明は見つかりませんでした。
編集:
同じインスタンスであるか、異なるインスタンスであるかは関係ありません。
int main()
{
Derived d1, d2; // Two different instances
d1.somethingDerived(d2); // This compiles fine
d1.somethingDerived(d1); // This compiles fine
return 0;
}
EDIT2:
アクセス権に関しては、クラスのinstanceが使用されているかどうかはまったく関係ないようです:
class Base
{
public:
void something(Base& b) // Another instance
{
++b.a; // But can enter private members
}
private:
int a;
};
C++のアクセス制御は(インスタンスごとではなく)クラスごとに機能しますが、protected
アクセス指定子にはいくつかの特性があります。
言語仕様では、派生クラスに属するいくつかのbaseサブオブジェクトの保護されたメンバーにアクセスしていることを確認する必要があります。基本型の関連のない独立したオブジェクトの保護されたメンバーにアクセスすることはできません。特に、ベース型のfreestandingオブジェクトの保護されたメンバーにはアクセスできません。派生オブジェクトにembeddedであるベースオブジェクトの保護されたメンバーにのみアクセスできます。
このため、pointer->member
構文、reference.member
またはobject.member
構文を介して保護されたメンバーにアクセスする必要があります。ここで、ポインター/参照/オブジェクトはを参照します派生クラス。
これは、あなたの例では、保護されたメンバーsomethingProtected()
はBase
オブジェクト、Base *
ポインター、またはBase &
参照を介してアクセスできませんが、Derived
オブジェクト、Derived *
ポインター、Derived &
参照。 this
のタイプはDerived *
であるsomethingProtected()
の単なる省略形であるため、プレーンなthis->somethingProtected()
アクセスが許可されます。
b.somethingProtected()
は上記の要件に違反しています。
上記の規則に従って、
void Derived::somethingDerived()
{
Base *b = this;
b->somethingProtected(); // ERROR
this->somethingProtected(); // OK
}
両方が同じエンティティにアクセスしようとしても、最初の呼び出しは失敗し、2番目の呼び出しはコンパイルされます。
基本クラスのメンバーにアクセスする方法について、混乱があると思います。それはこの方法だけです:
class Derived : public Base
void drivedMethod() {
Base::baseMethod();
}
この例では、別のインスタンスの保護されたメンバーにアクセスしようとしています。
派生インスタンスは、自身の保護されたメンバーにアクセスできますが、別のクラスのインスタンスの保護されたメンバーにはアクセスできません。これは仕様によるものです。
実際、別のクラスの保護されたメンバー、別のインスタンスメンバー、またはメイン関数からアクセスするのは、実際には両方ともパブリックアクセスです...
http://www.cplusplus.com/doc/tutorial/inheritance/ (アクセス指定子テーブルを探して、さまざまなレベルを確認します)
両方の例は、例えば同じことを証明しています:
void somethingDerived(Base& b)
{
b.somethingProtected(); // This does not
ここで、Derivedクラスはパラメーターとしてbを取得しているため、baseの別のインスタンスを取得しています。b.somethingProtectedはパブリックではないため、準拠しません。
これは従います:
void somethingDerived()
{
Base::somethingDerived();
別のdクラスのパブリックメソッドにアクセスしているので、2番目の例は問題ありません
> void somethingDerived(Base& b)
> {
> b.somethingProtected(); // This does not
> }
Derived
クラスは、Derived
オブジェクトの保護された基本メンバーにのみアクセスできます。 (必ずしも)Derived
オブジェクトではないオブジェクトのメンバーにはアクセスできません。失敗する場合は、Base &
を介してメンバーにアクセスしようとしていますが、これはDerived
ではないオブジェクトを参照している可能性があるため、アクセスできません。
あなたがしたことはC++では違法です。保護されたメンバーは、クラスのオブジェクトからアクセスできません。メンバー関数のみが保護されたメンバーにアクセスできます。 protected
メンバーは、派生クラスに継承されている間を除き、プライベートメンバーと同じように動作します。プライベートメンバー、パブリックメンバー、保護メンバーの違いを理解するために、以下のプログラムを検討してください。
class Base
{
private:
void somethingPrivate()
{
std::cout << "sasa" << std::endl;
}
public:
void somethingPublic()
{
std::cout << "haha" << std::endl;
}
protected:
void somethingProtected()
{
std::cout << "lala" << std::endl;
}
};
class Derived : public Base
{
public:
void somethingDerived()
{
Base b;
b.somethingPublic(); // Works fine.
somethingProtected(); // This is also fine because accessed by member function.
//b.somethingProtected(); // Error. Called using object b.
//somethingPrivate(); // Error. The function is not inherited by Derived.
}
};