c++類中的包含機制


 本人在學習Qt的時候發現了一個非常有趣的現象。有很多函數的調用方法都寫成了如下的形式:

object.func().func2();

這令小弟着實不懂。在上面這段代碼中,第一個對象調用它的成員函數func()是完全沒有問題的,但是后面那個func2()就奇怪了。我們只知道,點運算符(.)的作用就是調用對象的成員,但是如果按照上面這個程序的字面意思來理解,就是對象object調用它的成員函數func(),然后函數func()再調用它的成員函數func2()。這怎么能解釋得通哩??我們只知道對象有成員函數,但是從來沒有聽說過函數也可以有成員函數的啊。沒有辦法,只有翻C++的工具書,最后,居然發現了這個原來就是C++中的“包含”思想。那么究竟何為包含呢,且聽小弟慢慢敘來......^_^

      何為“包含”,其實說白了就是一個類可以包含另一個類的對象。即如下程序所示:

class A
{
                   //...
 
};
 
class B
{
                   //...
    A a;
    A b;
};

在上面這個程序中,我們定義了類A和類B。其中類B里面我們定義了類A的兩個對象a和b。這樣的情況就叫類B包含了類A。

下面,我們用一個程序來看一下“包含”:

 1 //#include <stdio.h>
 2 //#include <stdlib.h>
 3 #include <iostream>
 4 using namespace std;
 5 
 6 class A
 7 {
 8 public:
 9     A(int i) :x(i)
10     {
11         cout << "A's constructor" << endl;
12     }
13 
14     void getx()
15     {
16         cout << "A's a is" << x << endl;
17     }
18     ~A()
19     {
20         cout << "A's destructor" << endl;
21     }
22 
23 private:
24     int x;
25 
26 };
27 
28 class B
29 {
30 public:
31     B(int x,int z) :a(x), z(z)
32     {
33         cout << "B' constructor" << endl;
34     }
35 
36     A& getA()
37     {
38         return a;
39     }
40     
41     ~B()
42     {
43         cout << "B's destructor" << endl;
44     }
45 
46 private:
47     A a;
48     int z;
49 
50 
51 };
52 
53 void playstage()
54 {
55     B b1(1,2);
56     b1.getA().getx();
57 }
58 
59 void main()
60 {
61     playstage();
62     system("pause");
63     
64     
65 }
  • 首先對兩個類進行分析:在上面這個程序中,我們定義了兩個類A和B。其中可以看到,在類B的私有成員變量里面,我們定義了一個類B自己的成員變量,另外還定義了類A的對象a(47行);另外在類B的公有函數中,我們定義了返回值為類A的函數:getA(),它的作用就是返回在類B中定義的類A的對象a。在這里我們特別應該注意的是類B的構造函數:
B(int x,int z) :a(x), z(z)

這個構造函數很有意思。我們可以看到它不僅初始化了自己的私有成員變量z,而且也順帶初始化了類A的對象a。那么它肯定會調用類A的構造函數。然后再調用B類自己的構造函數。那么析構的時候順序應該就是相反的,首先調用B類的析構函數,然后再調用A類的析構函數。我們可以看到后面的程序輸出圖這樣說滴,^_^。(見輸出的紅色框)

此處怎么比我們預計的多了一項輸出呢?(箭頭所指處)。。

因為在調用b1.getA().getX()時,getA()返回了我們所創建的A類的對象a,此處相當於復制了一份(其實是調用了默認的copy構造函數)。所以我們最后需要多析構一次對象a.(作為返回值調用copy構造函數)

下面來印證我的猜想:

我們在類A中定義copy構造函數,其他代碼不變。

 1 class A
 2 {
 3 public:
 4     A(int i) :x(i)
 5     {
 6         cout << "A's constructor" << endl;
 7     }
 8     A(A &a)
 9     {
10         x = a.x;
11         cout << "A's copy constructor" << endl;
12     }
13     void getx()
14     {
15         cout << "A's a is" << x << endl;
16     }
17     ~A()
18     {
19         cout << "A's destructor" << endl;
20     }

輸出如下:

 

看到了吧!!    (0.0)

其實,我們為了避免拷貝構造函數的使用,我們可以返回A類的引用。這樣就避免了copy構造函數的調用。

    //A getA()
    A& getA()
    {
        return a;
    }

輸出如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM