C ++研究ノート11-組み合わせクラスと前方参照宣言の使用

クラスについては、以前の記事で、クラスとは何か、そのコンストラクター、およびそのコピーコンストラクターの役割について簡単に説明しました。前の記事の関連リンクは次のとおりです。
クラス定義と初期化
コピーコンストラクタとデストラクタ
次に、複合クラスを紹介します。複合クラスとは何ですか。組み合わせクラスの役割は何ですか?通常、クラスのオブジェクトを定義する場合、クラスメンバーの型は、実際にはint、float、doubleなどの基本データ型です。実際、クラスメンバーは、基本データ型だけでなく、カスタムデータ型にもなり得ます。つまり、データ型もクラスのオブジェクトになる可能性があるため、複合クラスが定義されている場合、クラスが構築される順序は非常に重要です。前述のコンストラクタを使用してクラスを初期化する
場合は、次のように構築シーケンスに従います。1。クラスのメンバータイプがクラスのオブジェクトである場合、最初にクラスメンバーデータの構造を初期化します。クラスメンバーは定義順に構築され、最初に定義して2を
構築します。コンストラクターは自分自身を構築しています。
問題を説明する例を次に示します。最初にポイントクラスを定義します。

class point 
{
    
    
private:
	int x,  y;
public:
	int getx() {
    
     return x; }
	int gety() {
    
     return y; }
	point(int xx = 0, int yy = 0) :x(xx), y(yy) {
    
     cout << "calling point init constructor" << endl; }//构造函数
	point(const point & p1);//复制构造函数


};

初期化コンストラクターを使用すると、対応するデバッグステートメントが出力されます。このクラスには整数xyも含まれます。
コピーコンストラクターは次のように定義されます。

point::point(const point &p1) {
    
    
	cout << "calling point copy constructor" << endl;
	x = p1.x;
	y = p1.y;
}

ポイントクラスのコピーコンストラクターが、対応するメンバーxyを別のメンバーに1つずつコピーしていることがわかります。
以下はラインクラスを定義し、ラインにはポイントクラスが含まれ、対応するラインは次のように定義されます。

class line {
    
    
private:
	double len;
	//私有成员为point类
	point p1, p2;
public:
	double getline() {
    
     return len; }
	line(point xp1, point xp2);//构造函数
	line(const line  &p11);//复制构造函数

};

行のデータメンバーとしてポイントクラスを使用して、複合クラスの使用を見てきました。コンストラクターのコンテンツを見てみましょう。

line::line(point xp1, point xp2):p1(xp1),p2(xp2)
{
    
    
	cout << "calling line init construct" << endl;
	double x = static_cast<double>(p1.getx() - p2.getx());
	double y = static_cast<double>(p1.gety() - p2.gety());
	len = sqrt(x*x + y*y);

}

単純な初期化リストを使用して、最初にポイントを初期化し、2つのポイントデータに基づいて距離を計算し、値をlenに割り当てていることがわかります。
ポイントのコピーコンストラクターを見てください

line::line(const line &p11 ) 
{
    
    
	cout << "calling line copy construct" << endl;
	p1 = p11.p1;
	p2 = p11.p2;
	len = p11.len;
}

上記はlineとpointのすべてのデータとコンストラクターです。以下では、main関数で次の構文のシーケンスを呼び出して観察します。コードは次のように表示されます。

# include <iostream>
# include <cmath>
using namespace std;
//类的组合,实际上我们在定义类的成员时通常会定义基础数据类型,实际上类的成员也可以是类的对象。
//类的组合描述的就是一个类内嵌其他类作为成员的情况。他们之间的关系是一种包含于被包含的关系
//值得注意的是类的构造顺序。
class point 
{
    
    
private:
	int x,  y;
public:
	int getx() {
    
     return x; }
	int gety() {
    
     return y; }
	point(int xx = 0, int yy = 0) :x(xx), y(yy) {
    
     cout << "calling point init constructor" << endl; }//构造函数
	point(const point & p1);//复制构造函数


};
point::point(const point &p1) {
    
    
	cout << "calling point copy constructor" << endl;
	x = p1.x;
	y = p1.y;
}
//类的组合
class line {
    
    
private:
	double len;
	//私有成员为point类
	point p1, p2;
public:
	double getline() {
    
     return len; }
	line(point xp1, point xp2);//构造函数
	line(const line  &p11);//复制构造函数

};
//组合类的构造函数
line::line(point xp1, point xp2):p1(xp1),p2(xp2)
{
    
    
	cout << "calling line init construct" << endl;
	double x = static_cast<double>(p1.getx() - p2.getx());
	double y = static_cast<double>(p1.gety() - p2.gety());
	len = sqrt(x*x + y*y);

}
//组合类复制构造函数
line::line(const line &p11 ) 
{
    
    
	cout << "calling line copy construct" << endl;
	p1 = p11.p1;
	p2 = p11.p2;
	len = p11.len;
}
int main()
{
    
    
	point p1(1, 1), p2(4, 5);
	line line1(p1, p2);
	line line2(line1);
	cout << "the line 1 length is" << endl;
	cout << line1.getline() << endl;
	cout << "the line 2 length is" << endl;
	cout << line2.getline() << endl;
	return 0;
	
}




コード操作の結果は次のとおりです
運転結果
。プログラム操作の結果を簡単に分析しましょう。最初に、コピーコンストラクターをいつ使用するかについてもう一度説明し
ます。1。既存のクラスを使用して別のクラスを初期化すると、初期化コンストラクターは次のようになります。と呼ばれる。
2.関数の仮パラメーターを仮想および実数と組み合わせると、関数のコピーコンストラクターが呼び出され
ます。3。クラスのオブジェクトが戻り値として使用される場合、コピーコンストラクターが呼び出されます。

int main()
{
    
    
	point p1(1, 1), p2(4, 5);//初始化两个point 调用初始化point
	line line1(p1, p2);//进入到line构造函数时虚实结合,调用了point复制构造函数,接着在初始化列表中,用已有的类成员初始化另一个数据成员再次调用初始化构造函数。最后调用line 初始化构造函数
	line line2(line1);//进入到复制构造函数中先构造其中的两个point类,
	//调用了其中复制构造函数
	cout << "the line 1 length is" << endl;
	cout << line1.getline() << endl;
	cout << "the line 2 length is" << endl;
	cout << line2.getline() << endl;
	return 0;
	
}

上記のクラスの組み合わせとコンストラクターの順序の分析では、クラスの前方参照宣言について説明します。クラスが最初に宣言されてから使用されることがわかります。2つのクラスが相互に呼び出す状況に遭遇すると、クラスの前方参照宣言が必要です。次のように

class b;
class a{
    
    

void(b a1);
};
class b{
    
    };

前方参照宣言が使用されていますが、クラスの詳細は、次のような完全なクラス定義が提供されるまで使用できないことに注意してください。

class b;
class a{
    
    

b a;
};
class b{
    
    };

bはクラスの完全な定義を与えることができないため、これは正しくありません。データ型を定義するときは、少なくともそれが占めるバイト数を知っておく必要があります。完全な詳細がないため、エラーが報告されます。
上記は、クラスの組み合わせと前方参照宣言の使用です。

おすすめ

転載: blog.csdn.net/qq_41803340/article/details/112596352