以下は、インスタンスの保護フィールドxにアクセスする微妙な例です。 BはAのサブクラスなので、タイプBの変数もタイプAです。なぜB :: foo()はbのxフィールドにアクセスできますが、aのxフィールドにはアクセスできないのですか?
class A {
protected:
int x;
};
class B : public A {
protected:
A *a;
B *b;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int v = b->x; // OK : accessing b's protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
ここに私がg ++で得るエラーがあります
$ g++ -c A.cpp
A.cpp: In member function ‘void B::foo()’:
A.cpp:3: error: ‘int A::x’ is protected
A.cpp:14: error: within this context
B
はA
からパブリックに継承されるため、Aの保護されたメンバーはBの保護されたメンバーになり、Bは通常どおりメンバー関数から保護されたメンバーにアクセスできます。つまり、B
のオブジェクトは、そのメンバー関数からB
の保護されたメンバーにアクセスできます。
ただし、Aの保護されたメンバーは、A
型のオブジェクトを使用して、クラスの外部にアクセスすることはできません。
標準(2003)の関連テキストは次のとおりです
11.5保護されたメンバーアクセス[class.protected]
派生クラスのフレンドまたはメンバー関数が基本クラスの保護された非静的メンバー関数または保護された非静的データメンバーを参照する場合、11.102節で前述したものに加えてアクセスチェックが適用されます)メンバーへのポインターを形成する場合(5.3 .1)、アクセスは、派生クラス自体(またはそのクラスから派生した任意のクラス)へのポインター、参照、またはオブジェクトを経由する必要があります(5.2.5)。アクセスがメンバーへのポインターを形成することである場合、nested-name-specifierは派生クラス(またはそのクラスから派生した任意のクラス)に名前を付けます。
そして、この例は標準(2003)自体から次のようになります。
_[Example:
class B {
protected:
int i;
static int j;
};
class D1 : public B {
};
class D2 : public B {
friend void fr(B*,D1*,D2*);
void mem(B*,D1*);
};
void fr(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // OK (access through a D2)
p2->B::i = 4; // OK (access through a D2, even though naming class is B)
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
B::j = 5; // OK (because refers to static member)
D2::j =6; // OK (because refers to static member)
}
void D2::mem(B* pb, D1* p1)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
i = 3; // OK (access through this)
B::i = 4; // OK (access through this, qualification ignored)
int B::* pmi_B = &B::i; // ill-formed
int B::* pmi_B2 = &D2::i; // OK
j = 5; // OK (because j refers to static member)
B::j = 6; // OK (because B::j refers to static member)
}
void g(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
p2->i = 3; // ill-formed
}
—end example]
_
上記の例では、fr()
は_D2
_のフレンド関数であり、mem()
は_D2
_のメンバー関数であり、g()
は友達も会員も機能しません。
検討してください:
class A {
protected:
int x;
};
class C : public A
{
};
class B : public A {
protected:
unique_ptr<A> a;
public:
B() : a(new C) // a now points to an instance of "C"
{ }
void foo() {
int w = a->x; // B accessing a protected member of a C? Oops.
}
};
公開継承:
基本クラスのすべての_Public members
_は、派生クラスの_Public Members
_になります&
基本クラスのすべての_Protected members
_は、_Protected Members
_の_Derived Class
_になります。
上記のルールに従って:x
の保護されたメンバーA
がクラスB
の保護されたメンバーになります。
_class B
_は、メンバー関数foo
で独自の保護されたメンバーにアクセスできますが、すべてのA
クラスから派生したわけではないA
のメンバーにのみアクセスできます。
この場合、_class B
_にはA
ポインターa
が含まれています。この含まれているクラスの保護されたメンバーにアクセスできません。
_B::foo()
に含まれる_class B
_ポインタb
?
ルールは:
C++では、アクセス制御はオブジェクトごとではなく、クラスごとに機能します。
したがって、_class B
_のインスタンスは、_class B
_の別のインスタンスのすべてのメンバーに常にアクセスできます。
ルールを示すコードサンプル:
_#include<iostream>
class MyClass
{
public:
MyClass (const std::string& data) : mData(data)
{
}
const std::string& getData(const MyClass &instance) const
{
return instance.mData;
}
private:
std::string mData;
};
int main() {
MyClass a("Stack");
MyClass b("Overflow");
std::cout << "b via a = " << a.getData(b) << std::endl;
return 0;
}
_
B :: foo()がbのxフィールドにアクセスできるが、aのxフィールドにはアクセスできないのはなぜですか?
保護されたメンバーには、同じクラス(または派生クラス)の他のメンバーのみがアクセスできます。
_b->x
_は(継承により)クラスBのインスタンスの保護されたメンバーを指すため、B::foo()
はそれにアクセスできます。
_a->x
_はクラスAのインスタンスの保護されたメンバーを指しているため、B::foo()
はそれにアクセスできません。
クラスB
は、クラスA
と同一ではありません。そのため、クラスB
のメンバーは、クラスA
の非公開メンバーにアクセスできません。
一方、クラスB
derivesはクラスA
からパブリックに公開されるため、クラスB
には、クラスx
のすべてのメンバーがアクセスできる(保護された)メンバーB
があります。
基本的な概念から始めましょう
class A {
protected:
int x;
};
class B : public A {
public:
void foo() {
int u = x; // OK : accessing inherited protected field
}
};
子は親を継承しているため、子はxを取得します。したがって、子のfoo()メソッドでxに直接アクセスできます。これは、保護された変数の概念です。子の親の保護された変数に直接アクセスできます。注:ここでは、xには直接アクセスできますが、Aのオブジェクトからはアクセスできないと言っています。違いは何ですか? xは保護されているため、Aの外部にあるAの保護されたオブジェクトにアクセスすることはできません。そのため、次の方法ではアクセスできません
class B : public A {
protected:
A *a;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
ここに興味深いコンセプトがあります。クラス内のオブジェクトを使用して、クラスのプライベート変数にアクセスできます!
class dummy {
private :
int x;
public:
void foo() {
dummy *d;
int y = d->x; // Even though x is private, still you can access x from object of d - But only with in this class. You cannot do the same outside the class.
}
};
//同じは保護された変数のためです。したがって、次の例にアクセスできます。
class B : public A {
protected:
A *a;
B *b;
public:
void foo() {
int u = x; // OK : accessing inherited protected field x
int y = b->x; // OK : accessing b's protected field x
int w = a->x; // ERROR : accessing a's protected field x
}
};
それが説明することを願っています:)
C++は完全なオブジェクト指向プログラミングであり、Javaは純粋なオブジェクト指向です:)