剛開始編程的時候,我相信大家都跟我一樣,是這樣把兩個類聯系起來的(現用類A和類B舉例):
class A
{
private:
B *b;
test1;
}
這樣,當a需要的時候可以調用B類的函數方法
這樣的缺點是:
1:A可以使用B的方法,B不可以使用A的方法(B看不到A);
2:內聚性弱,也就是a對象消失b對象一定消失(想像一下a,b是兩個窗口,a是登陸,b是主頁,當點擊a上的按鈕時生成b,但a界面不能消失釋放,但實際情況下登陸成功后登陸界面消失),b對象生成失敗a對象也就失敗。
3:如果三個類,四個類,五個類之間交流,互相交流,但上述方法不可能實現
這個問題一直困擾了我很久,上述簡單處理雖然可以解決一些基本的問題,但事實上兩個類是如何通信 的呢?
如果B要訪問A中的test1,不可能直接訪問,但是A即可訪問本類成員,也可訪問B的成員,因此可以在A中設置test1作為參數直接傳給B中的成員,或者通過函數形式春給B。該方法的缺點也在於此,要動用A。
如果B要訪問A中的函數,???能傳函數指針嗎。???
B調用A的回調函數,肯定可以。回調函數的定義和使用都在B中,但是設定回調函數需在A中。
A訪問B的話,可以調用B的指針訪問,或者A的函數包含B的函數,包含B的成員等。
如果A與B沒有任何關系,則用友元函數。 全局變量
基本的思想:如果本類中無法訪問某個變量或者函數,首先找到具有權限的類。通過該類的權限,間接訪問它。
其實方法有很多,大體思路是這樣的:
定義一個類M,在M中讓A和B作為其成員變量,(這樣M中的函數就可以調用A,B中的函數方法),當A中想要發消息給B時,想方設法把消息給M,M再調用B中的函數傳給B,那么這個"想方設法"是什么方法呢?
開始我是這么想的
M::M()
{
a=new A(this);//把當前的this指針傳給a,這樣在a的函數里就可以調用M的函數了。
}
編譯會發生錯誤
為什么捏? 是這樣滴:在寫類M的時候,要包含頭文件#include“A.h”有木有!!,在寫類A的函數的時候要包含頭文件#include"M.h"有木有!!(因為在A的構造里要定義一個M類型的指針做實參啊!),這里就有問題,計算機執行時,1:走到#include“A.h”這一行代碼時要先看看A.h里有什么。2:走到A.h里的時候,發現有#include"M.h"這行代碼,然后又進入M.h看看,3:執行1步驟。。。。。是不是循環,無限循環有木有!!!所以報錯。
解決方法有很多,例如監聽A的函數,利用函數指針,利用全局函數(全局函數簡單好用,但破壞了面向對象的封裝性)
好了,不羅嗦了,正確答案如下:
用接口函數,interface,在c++下沒有定義接口函數,其實接口函數就是純虛函數,在vc下(別的我不知道行不行)可以這樣:
純虛類是因為class不產生虛表,只能在派生類中實現虛表;C++中沒有提供類似interface這樣的關鍵字來定義接口,但是Mircrosoft c++中提供了__declspec(novtable)來修飾一個類,來表示該類沒有虛函數表,也就是虛函數都(應該)是純虛的。減小SIZE 是因為虛表是需要空間的,在不需要虛表的情況下,把虛表去掉就可以減少SIZE了。
#include <IOSTREAM>
using namespace std;
#define interface class __declspec(novtable)
interface InterFace
{
virtual void f();
};
為了解決那個讓計算機迷糊的問題,我們讓M繼承InterFace,然后傳參的時候傳InterFace類型的,這樣就不會重復包含了,試試:
#include"Interface.h"
#include"A.h"
#include"B.h"
class M :public InterFace//繼承必須包含頭文件定義,聲明沒有用
{
private:
A *a;
B *b;
public:
M()//構造
{
a=new A(this);//因為M繼承InterFace所以可以用父類的指針來作為它的實參!
b=new B();
}
void f()
{
b->show();//調用B類方法
}
};
在A類:
#include"InterFace.h"
class A
{
public:
A(InterFace *i)
{
printf("A要調用M中的f()函數,讓f()函數調用B的函數,這樣A就成功通信到了B!");
i->f();//這里調用的是InterFace的f函數,不過在M類中實例化了
}
};
在B類:
#include"stdio.h"
class B
{
public:
void show()
{
printf("我被M調用了!");
}
};
int mian()
{
M m;
return 0;
}
累死我了!!如有紕漏,望請見諒()以上皆為小馮同學總結,大家復制粘貼的時候不要把這句話刪了,3Q!!