1. 程式人生 > >C++中兩個類互相引用的解決方法

C++中兩個類互相引用的解決方法

轉載自  ---》 https://blog.csdn.net/xiqingnian/article/details/41214539

一、問題描述

現在有兩個類A和B需要定義,定義A的時候需要用到B,定義B的時候需要用到A。

二、分析

A和B的定義和呼叫都放在一個檔案中肯定是不可以的,這樣就會造成兩個迴圈呼叫的死迴圈。

根本原因是:定義A的時候,A的裡面有B,所以就需要去檢視B的佔空間大小,但是檢視的時候又發現需要知道A的佔空間大小,造成死迴圈。

解決方法:

(1)寫兩個標頭檔案A.h和B.h分別用於宣告類A和B;

(2)寫兩個.cpp檔案分別用於定義類A和B;

(3)在A的標頭檔案中匯入B的標頭檔案;

(4)在B的標頭檔案中不匯入A的標頭檔案,但是用extern 的方式宣告類A,並且,在B中使用A的時候要用指標的形式。

原理:在B中用指標呼叫A,那麼在A需要知道B佔空間大小的時候,就會去找到B的定義檔案,雖然B的定義檔案中並沒有匯入A的標頭檔案,不知道A的佔空間大小,但是由於在B中呼叫A的時候用的指標形式,B只知道指標佔4個位元組就可以,不需要知道A真正佔空間大小,也就是說,A也是知道B的佔空間大小的。

我的理解--》必須得其中一個是指標,通過指標(4位元組) + extern 宣告的方式,來保證編譯B.h的時候,能通過;這樣在編譯A.h的時候,直接就可以通過了

三、C++示例

A的標頭檔案A.h:

  1. #ifndef _A
  2. #define _A
  3. <strong>    #include "B.h"//A的標頭檔案匯入了B的標頭檔案</strong>
  4. //extern class B;
  5. class A
  6. {
  7. private:
  8. int a;
  9. B objectb;//A的標頭檔案匯入了B的標頭檔案,在呼叫B的時候就可以不用指標
  10. public:
  11. A();
  12. int geta();
  13. void handle();
  14. };
  15. #endif _A


B的標頭檔案B.h:

  1. #ifndef _B
  2. #define _B
  3. <strong>//#include "A.h"//B的標頭檔案沒有匯入A的標頭檔案,需要有三個地方需要注意!
  4. extern class A;//注意1:需要用extern宣告A</strong>
  5. class B
  6. {
  7. private:
  8. int b;
  9. A* objecta;//注意2:呼叫A的時候需要用指標
  10. public:
  11. B();
  12. int getb();
  13. void handle();
  14. };
  15. #endif _B


A的定義檔案A.cpp:

  1. #include <iostream>
  2. <strong>#include "A.h"</strong>
  3. using namespace std;
  4. A::A()
  5. {
  6. this->a=100;
  7. }
  8. int A::geta()
  9. {
  10. return a;
  11. }
  12. void A::handle()
  13. {
  14. cout<<"in A , objectb.b="<<objectb.getb()<<endl;
  15. }


B的定義檔案B.cpp:

  1. #include <iostream>
  2. <strong>#include "B.h"
  3. #include "A.h"//注意3:在B.cpp裡面匯入A的標頭檔案</strong>
  4. using namespace std;
  5. B::B()
  6. {
  7. this->b=200;
  8. }
  9. int B::getb()
  10. {
  11. return b;
  12. }
  13. void B::handle()
  14. {
  15. objecta=new A();
  16. cout<<"in B , objecta->a="<<objecta->geta()<<endl;
  17. }


main.cpp:

  1. #include <iostream>
  2. #include <cstdlib>
  3. <strong>#include "A.h"
  4. //#include "B.h" //因為A.h裡面已經包含B.h,所以在此不需要匯入B.h了。</strong>
  5. using namespace std;
  6. void main()
  7. {
  8. A a;
  9. a.handle();
  10. B b;
  11. b.handle();
  12. system("pause");
  13. }

相關推薦

C++互相引用解決方法

轉載自  ---》 https://blog.csdn.net/xiqingnian/article/details/41214539一、問題描述現在有兩個類A和B需要定義,定義A的時候需要用到B,定義B的時候需要用到A。二、分析A和B的定義和呼叫都放在一個檔案中肯定是不可以

c++互相引用的問題

pro 如何 ++ code 泛型 cin padding 直接 fine 原文鏈接http://www.cnblogs.com/weixliu/p/3957227.html   最近在改一個C++程序的時候碰到一條警告信息,警告信息為:“

C++互相包含

今天突然想起一個C++的問題,如果一個類A包含類B的例項,而例項B也包含另一個類A,這種方式的程式碼應該怎麼寫,按照一般的開發者的想法的程式碼如下: 檔案A.h #include "B.h" #include <iostream> usin

c++的標頭檔案互相包含編譯出錯的解決辦法

首先我們需要問一個問題是:為什麼兩個類不能互相包含標頭檔案? 所謂互相包含標頭檔案,我舉一個例子:我實現了兩個類:圖層類CLayer和符號類CSymbol,它們的大致關係是圖層裡包含有符號,符號裡定義一個相關圖層指標,具體請參考如下程式碼(注:以下程式碼僅供說明問題,不作為

C++互相引用

A.h #include "A.h" #include "B.h" class A {  ...     B b; }   B.h class A; class B {   ...  

c++ 互相引用的問題

現在有兩個類要相互應用時,會出現各種各樣的問題,首先看第一個例子: #ifndef AH #define AH class B; class A { B *memb; A() { } ~A() { dele

C++相互包含引用問題

在構造自己的類時,有可能會碰到兩個類之間的相互引用問題,例如:定義了類A類B,A中使用了B定義的型別,B中也使用了A定義的型別 class A { int i; B b; } class B { int i; A* a; } 請注意上面的定義內容,一般情況下是不能出現類A,

C++設計技巧(一)之互相擁有對方的物件指標

1、在實際的運用中我們也會用到如下的類關係: class B; class A { int i; B *lpb; } class B { int i; A* lpa; } 注意:一般來說,兩者的定義,至少有一方是使用指標,或兩者都使用指標,但是決不能兩者都定義實體物件。 這樣的實

相互引用解決方法

1 問題提出 最近在編寫“鬥地主”遊戲,在程式中有一個“CDealer”類用來實現發牌等等功能,還有一個“CPoker”類,用來表示撲克牌。在CDealer類中包含了一個CPoker類指標的成員變數,而在CPoker類中也包含了一個CDealer類指標的成員變數,如下所示:

關於js物件函式互相呼叫,其中一個為定時器宣告,定時器迴圈報錯問題(記錄一次嘗試新寫法的報錯經歷)附帶無縫輪播圖程式碼

先上之前的錯誤程式碼吧,注意計時器這個方法(是想把之前寫的的輪播圖演示重構一下) var obj = { sleepTime: 2000,//輪播延時 cont: 0,//第幾張 origin: document.getElementsByClassName('main-

C++常用的控制語句格式的函式(width和precision函式)

width 語法: int width(); int width( int w ); 函式 width()返回當前的寬度。可選擇引數w用於設定寬度大小。寬度是指每一次輸

關於js物件函式互相呼叫,其中一個為定時器宣告,定時器迴圈報錯問題(記錄一次嘗試新寫法的報錯經歷)

先上之前的錯誤程式碼吧(是想把之前寫的的輪播圖demo重構一下) var obj = { sleepTime: 2000,//輪播延時 cont: 0,//第幾張 origin: document.getElementsByClassName('ma

C#Form視窗之間的傳值(父->子)(子->父)

首先定義兩個Form,一個為Form1,一個為Form2,其中Form1作為父視窗,Form2作為子視窗 1、父視窗傳值給子視窗       Form1中程式碼:         public Form1()         {             Initialize

QT 實現一個服務端接收客戶端的解決方法

最近自己在折騰QT中實現TCP服務端的過程中,發現以往的例子都是點對點的,也就是說大都是一個客戶端,一個服務端,然後兩個進行通訊,而對於單個服務端與多個客戶端的通訊,非常稀少,找到一個但對於我們新手來說,有點複雜,不好理解,下面我介紹一個新手也能明白的一種解決方案。下面是ma

C#視窗怎麼傳遞引數?或者怎麼使用另一個視窗的控制元件呢?

在主視窗中開啟一個新的視窗,怎麼傳遞引數呢?這個新視窗怎麼呼叫舊的視窗的控制元件呢? 假如主視窗是Form1,新視窗是Form2。首先新增引用:using System.Windows.Forms; class Form1:Form { public Form1()

C++##(井號)和#(一個井號)用法

C(和C++)中的巨集(Macro)屬於編譯器預處理的範疇,屬於編譯期概念(而非執行期概念)。下面對常遇到的巨集的使用問題做了簡單總結。 關 於#和## 在C語言的巨集中,#的功能是將其後面的巨集引數進行字串化操作(Stringfication),簡單說就是在對它所引用的巨

Windows10操作系統出現移動盤符解決方法

Windows10操作系統出現兩個移動盤按照下面的註冊鍵值,將{F5FB2C77-0E2F-4A16-A381-3E560C68BC83}鍵值前增加一個“-”即可。HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\

【Linux】U盤安裝Centos6.3遇到的重要問題及其解決方法

  之前裝過無數遍windows系統,對系統分割槽神馬的也算比較瞭解,以為安裝CentOS的過程應該也差不多,但是沒想到遇到兩個比較重要的問題,百度了一番才恍然大悟,特此記錄一下,對初學者應該有所幫助。    第一個問題:boot loader的安裝位置

關於unix下tar解壓時的錯誤問題及解決方法

---------------------------------------------------------------------------- ---- 本文為andkylee個人原創,請在尊重作者勞動成果的前提下進行轉載; ---- 關鍵字: 解壓 tar 錯誤

詳解關於 C# Linq 隨機排序的有效解決方法

在做資料操作的時候,隨機排序難免都會遇到。而如果使用 Linq 進行資料操作的話,你會發現 Linq 並沒有提供隨機排序的方法。而百度一下“Linq 隨機排序”可以找到N多的方法,要非常簡單的也有,要非常複雜也有,但是,這些方法裡也有N多是行不通的,也有看到一篇博文,列出了