C++
Base
基本クラスと派生クラスが与えられた場合、のDerived
コンストラクターによって最初に構築されるDerived
のはBase
サブオブジェクトです。これはサブオブジェクトと呼ばれるため、オブジェクトでドット演算子を使用することにより、他のメンバー オブジェクトと同様にクライアント コードからアクセスできると想定しましたDerived
。Derived
また、 によって の実装コードからアクセスできると仮定しましたthis->Base
。セミコロンが後に続く、既に初期化されているオブジェクトの名前だけで構成されるステートメントは、コンパイルする必要がありますが、効果はありません。そのロジックに従って、Derived
objectを指定して、次のmyderived
ことを試しました:myderived.Base;
クライアント コードthis->Base;
内およびDerived
の実装内で、どちらのステートメントもコンパイルされません。
なんで?Base
は、それ自体がBase
クラスの名前であり、オブジェクトの名前ではないことを知っていBase
ます。しかし、 (クライアント コード) または(実装コード) プレフィックスBase
によって修飾されたものは基本サブオブジェクトを参照すると思いました。以下のコードを参照してください。これは (コメントアウトされたコードは別として) VC12 および g++ 4.8 で動作します。extendsとの定義はデータ メンバーを宣言するので、私のオブジェクトには 2 つが含まれている必要がありますmyderived.
this->
Base
Base
Derived
Derived
Base
Derived
Base
membase
Derived
Base
オブジェクト。コンパイルの成功がコンパイラ標準の不適合の結果ではないと仮定すると、2 つの異なるオブジェクトのint
メンバーに異なる値を示すコンソール出力 (コメント内) は、 inの ctor 初期化子が継承されたサブオブジェクトは、宣言されたデータ メンバー オブジェクトを参照します。の ctor 初期化子では、オブジェクトやクラスだけでなく、継承されたサブオブジェクトを具体的に参照します。n
Base
Derived
Base
Base
membase
Derived
Base
Base
Base
#include <iostream>
struct Base {
Base(int par) : n(par) {}
void foo() { std::cout << "Base: " << n << std::endl; }
int n;
};
struct Derived : Base {
Derived() : Base(2), membase(3) {}
Base membase;
void foo() { std::cout << "Derived: " << n << std::endl; }
// void g() { this->Base; } // Error in VC12 & g++ 4.8
// ^ VC12: error C2273: 'function-style cast' : illegal as
// right side of '->' operator
};
int main() {
Derived myderived;
// myderived.Base; //Error in VC12 & g++ 4.8
// ^ VC12: error C2274: 'function-style cast' : illegal as
// right side of '.' operator
myderived.foo(); // OUTPUT: "Derived: 2"
myderived.Base::foo(); // OUTPUT: "Base: 2"
myderived.membase.foo(); // OUTPUT: "Base: 3"
}
繰り返しますが、継承されたサブオブジェクトを一意に参照してコンパイルするべきではありません
myderived.Base;
か?this->Base;
Base
は、サブオブジェクト、クラス、または何かを参照してい
Base
ますか?myderived.Base
this->Base
Base
Base
一般に、継承された基本サブオブジェクトは派生クラスのデータ メンバーと見なされますか?
の観点から、
Derived
のコンストラクター初期化子のBase
コンテキスト内で継承されたサブオブジェクトのみを参照し、の ctor 初期化子の外側のクラスのみを参照しますか?Derived
Base
Derived
の実装コードとクライアント コードで「
Base
オブジェクトの継承されたサブオブジェクト」Derived
を表現するにはどうすればよいでしょうか。Base
Derived
Derived
でスコープ解決演算子を使用すると、
myderived.Base::foo()
はfoo()
のメソッドでありBase
、VC12 および g++ 4.8 でコンパイルされます。とドット演算子で修飾されているため、これBase
は のデータ メンバであることを意味しますか? もしそうなら、それはクラスですか、それともサブオブジェクトですか?myderived
myderived
Base
Base
Base
しかし
myderived.Base.foo()
、コンパイルされません。オブジェクトのメンバーのAFAIKアクセスは、オブジェクト名とドット演算子によってクライアントコードで修飾されています。オブジェクト名とドット演算子の代わりに、スコープ解決演算子によって修飾される 2 種類のものは、(a) 名前空間に属するものへの外部アクセス、および (b) 静的データ メンバーの名前とメンバー関数の名前です。クラス定義の外側で定義された定義の場合、 のBase
前にあるはインスタンスではなくクラス::
を参照します。これは in が名前空間であるか、クラスを参照していることを意味しますか?Base
Base
Base
myderived.Base
もしそうなら、それは名前空間であるか、それとも
::
のメンバーが後に続くかどうかに基づいて条件付きのクラスを参照していますBase
か?#7 の答えが「はい」の場合、その理由は何ですか? 次のロジックとは矛盾しているように思われます: 名前空間で 1 つの変数を囲んでも、それ自体では、名前空間がその変数の型の他のインスタンスを囲んだり構築したりすることはできません。名前空間は、その型のインスタンスを 1 つだけ所有します。つまり、その型に含まれる変数です。静的データ メンバーのように、クラスの一部であるメンバーにも同じことが言えます。このクラスは、その型のインスタンスを 1 つだけ所有します。つまり、クラスに含まれる静的データ メンバーです。対照的に、クラスのインスタンスと同じ数の同じ名前の非静的データ メンバーがクラスに存在します。
指定されたメソッド
h()
およびオブジェクトは、VC12 および g++ 4.8 でコンパイルされます。さらに、g++ 4.8 では、 のように、そのステートメントで任意の数の余分な s を使用できます。このようなステートメントは、 が のメンバーであることを暗示しているようです。しかし、VC12 は. しかし、 objectが与えられた場合、VC12 は問題なくコンパイルされます。これは、VC12 がクラスをそれ自体のメンバーとして扱っても問題ないことも意味します。しかし、それは、以前の声明を編集できないことと矛盾しています。また、VC12 は、任意の数の余分なs (たとえば) を持つのバージョンをコンパイルできませんが、g++ はコンパイルできます。もしあれば、どのコンパイラが正しいですか?Base
Derived
myderived
myderived.Base::h();
Base::
myderived.Base::Base::h();
Base
Base
error C3083: '{ctor}': the symbol to the left of a '::' must be a type
Base
mybase
mybase.Base::h();
mybase.Base::h();
Base::
mybase.Base::Base::h()
いずれにせよ、それは名前空間またはクラスがそれ自体を含むことができるということですか?
int
グローバル変数が与えられた場合x
、ステートメント::::x;
(2 つのスコープ解決演算子を含む) はどちらのコンパイラでもコンパイルされないため、グローバル スコープにはグローバル スコープが含まれていないと想定しています。