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