継承 - 派生クラス c++




派生クラスがこのコードで保護されたメンバ関数を呼び出せないのはなぜですか? (3)

C ++でのアクセス制御は、(インスタンス単位ではなく)クラス単位で動作しますが、 protectedアクセス指定子にはいくつかの特質があります。

言語仕様では、派生クラスに属する基本サブオブジェクトの保護されたメンバーに確実にアクセスする必要があります。 無関係な基本型の独立したオブジェクトの保護されたメンバーにアクセスすることはできません。 特に、基底型のフリースタンディングオブジェクトの保護されたメンバーにアクセスすることはできません。 ベースサブオブジェクトとして派生オブジェクトに埋め込まれた基本オブジェクトの保護されたメンバーにのみアクセスできます。

このため、 pointer->member構文、 reference.memberまたはobject.member構文で保護されたメンバーにアクセスする必要がpointer->memberます。ポインタ/参照/オブジェクトは派生クラスを参照します。

つまり、あなたの例では、保護されたメンバーのsomethingProtected()は、 Baseオブジェクト、 Base *ポインタまたはBase & referencesからアクセスできませんが、 Derivedオブジェクト、 Derived *ポインタ、 Derived & Reference Derived *アクセスできます。 あなたは普通のsomethingProtected()アクセスが許可されています。 thisthis->somethingProtected()省略形であり、 thisDerived *型です。

b.somethingProtected()は上記の要件に違反します。

上記の規則に従って

void Derived::somethingDerived()
{
    Base *b = this;
    b->somethingProtected();    // ERROR
    this->somethingProtected(); // OK
}

両方とも同じエンティティにアクセスしようとしても、最初の呼び出しは失敗し、2番目の呼び出しはコンパイルされます。

#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;
}

保護されたメンバーのみが使用でき、他のインスタンスの保護されたメンバーは永遠に到達できないと考えました。

しかし:

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:

アクセス権に関しては、クラスのどのインスタンスが使用されているかはまったく重要ではないようです。

class Base
{
public:
    void something(Base& b)  // Another instance
    {
        ++b.a;               // But can enter private members
    }

private:
    int a;
};

Derivedクラスは、 Derivedオブジェクト内の保護された基本メンバにのみアクセスできます。 (必然的に) Derivedオブジェクトではないオブジェクト内のメンバにアクセスすることはできません。 失敗した場合、 Base &を介してメンバーにアクセスしようとしています。これはDerivedではないオブジェクトを参照する可能性があるため、アクセスできません。


私は基本クラスのメンバーにアクセスする方法にいくつかの混乱があると信じています。 それはこの方法だけです:

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を取得していますので、b.somethingProtectedはpublicではないため、別のインスタンスのbaseを取得しています。

これは準拠します:

void somethingDerived()
{
   Base::somethingDerived();

もう1つのdクラスのパブリックメソッドにアクセスしているため、2番目の例は正常に準拠しています

>  void somethingDerived(Base& b)
>     {
>         b.somethingProtected();  // This does not
>     }




oop