1.構造函數、析構函數與拷貝構造函數介紹
構造函數
		1.構造函數不能有返回值
		2.缺省構造函數時,系統將自動調用該缺省構造函數初始化對象,缺省構造函數會將所有數據成員都初始化為零或空
		3.創建一個對象時,系統自動調用構造函數
析構函數
		1.析構函數沒有參數,也沒有返回值。不能重載,也就是說,一個類中只可能定義一個析構函數
		2.如果一個類中沒有定義析構函數,系統也會自動生成一個默認的析構函數,為空函數,什么都不做
		3.調用條件:1.在函數體內定義的對象,當函數執行結束時,該對象所在類的析構函數會被自動調用;2.用new運算符動態構建的對象,在使用delete運算符釋放它時。
拷貝構造函數
拷貝構造函數實際上也是構造函數,具有一般構造函數的所有特性,其名字也與所屬類名相同。拷貝構造函數中只有一個參數,這個參數是對某個同類對象的引用。它在三種情況下被調用:
		1.用類的一個已知的對象去初始化該類的另一個對象時;
		2.函數的形參是類的對象,調用函數進行形參和實參的結合時;
		3.函數的返回值是類的對象,函數執行完返回調用者。
【代碼】
			#include "stdafx.h"
			#include <iostream>
			using namespace std;
			class point
			{
			private:
			    int x, y;
			public:
			    point(int xx = 0, int yy = 0)
			    {
			        x = xx;
			        y = yy;
			        cout << "Constructor" << endl;
			    }
			    point(const point &p)
			    {
			        x = p.x;
			        y = p.y;
			        cout << "Copy Constructor" << endl;
			    }
			    ~point()
			    {
			        cout << "Destructor" << endl;
			    }
			    int get_x()
			    {
			        return x;
			    }
			    int get_y()
			    {
			        return y;
			    }
			};
			
			void f(point p)
			{
			    // copy constructor
			    cout << p.get_x() << "  " << p.get_y() << endl;
			    // destructor
			}
			point g()
			{
			    point a(7, 33); //constructor
			    return a; // copy constructor    temp object
			}
			void test()
			{
			    point a(15, 22); // constructor
			    point b(a); //(1) copy constructor
			    cout << b.get_x() << "  " << b.get_y() << endl; // 15 22
			    f(b);//  (2) copy constructor
			    b = g(); // (3) copy constructor
			    cout << b.get_x() << "  " << b.get_y() << endl; // 7  33
			}
			int main()
			{
			    test();
			    return 0;
			}
			/*
			Constructor
			Copy Constructor
			15      22
			Copy Constructor
			15      22
			Destructor
			Constructor
			Copy Constructor
			Destructor
			Destructor
			7       33
			Destructor
			Destructor
			*/
2. 繼承關系中構造函數執行順序
		(1)任何虛擬基類(virtual)的構造函數按照它們被繼承的順序構造;
		(2)任何非虛擬基類(non-virtual)的構造函數按照它們被繼承的順序構造;
		(3)任何成員對象(data member)的構造函數按照它們聲明的順序調用;
		(4)類自己的構造函數(self)。
【代碼】
			#include "stdafx.h"
			#include <iostream>
			using namespace std;
			
			class OBJ1
			{
			public:
			    OBJ1()
			    {
			        cout << "OBJ1/n";
			    }
			};
			class OBJ2
			{
			public:
			    OBJ2()
			    {
			        cout << "OBJ2/n";
			    }
			};
			class Base1
			{
			public:
			    Base1()
			    {
			        cout << "Base1/n";
			    }
			};
			class Base2
			{
			public:
			    Base2()
			    {
			        cout << "Base2/n";
			    }
			};
			class Base3
			{
			public:
			    Base3()
			    {
			        cout << "Base3/n";
			    }
			};
			class Base4
			{
			public:
			    Base4()
			    {
			        cout << "Base4/n";
			    }
			};
			class Derived : public Base1, virtual public Base2,
			    public Base3, virtual public Base4
			{
			public:
			    Derived() : Base4(), Base3(), Base2(),
			        Base1(), obj2(), obj1()
			    {
			        cout << "Derived./n";
			    }
			protected:
			    OBJ1 obj1;
			    OBJ2 obj2;
			};
			void test()
			{
			    Derived aa;
			    cout << "This is ok./n";
			}
			int main()
			{
			    test();
			    return 0;
			}
			/*
			Base2
			Base4
			Base1
			Base3
			OBJ1
			OBJ2
			Derived.
			This is ok.
			*/
【代碼2】
			#include "stdafx.h"
			#include <iostream>
			using namespace std;
			class Base1
			{
			public:
			    Base1(int i)
			    {
			        cout << "Base1 " << i << endl;
			    }
			};
			class Base2
			{
			public:
			    Base2(int i)
			    {
			        cout << "Base2 " << i << endl;
			    }
			};
			class Base3
			{
			public:
			    Base3()
			    {
			        cout << "Base3 *" << endl;
			    }
			};
			class Derived : public Base2,  public Base1, virtual public Base3
			{
			public:
			    Derived(int a, int b, int c, int d, int e)
			        : Base1(a), b2(d), b1(c), Base2(b)
			    {
			        m = e;
			        cout << "Derived./n";
			    }
			protected:
			    Base1 b1;
			    Base2 b2;
			    Base3 b3;
			    int m;
			};
			void test()
			{
			    Derived aa(1, 2, 3, 4, 5);
			    cout << "This is ok./n";
			}
			int main()
			{
			    test();
			    return 0;
			}
			/*
			Base3 *
			Base2 2
			Base1 1
			Base1 3
			Base2 4
			Base3 *
			Derived.
			This is ok.
			*/
分析:
(1) virtual
按照繼承順序:Base3
第一步:先繼承Base3,在初始化列表里找不到Base3(), 則調用Base3里的默認構造函數Base3(),打印"Base3 *"
(2)non-virtual
按照繼承順序:Base2,Base1
第二步:繼承Base2,在初始化列表中找Base2(b),調用Base2的構造函數Base2(2),打印"Base2 2"
第三步:繼承Base1,在初始化列表中找Base1(a),調用Base1的構造函數Base1(1),打印"Base1 1"
(3)data member
按照申明順序:b1,b2,b3
第四步:構造b1,在初始化列表中找b1(c),調用Base1的構造函數Base1(3),打印"Base1 3"
第五步:構造b2,在初始化列表中找b2(d),調用Base2的構造函數Base1(4),打印"Base2 4"
第六步:構造b3,在初始化列表中找不到b3(),調用Base3的構造函數Base3(),打印"Base3 *"
(4)self
第7步:執行自己的構造函數體,輸出"Derived."
新聞熱點
疑難解答