1. 程式人生 > >類和結構體的遞迴定義

類和結構體的遞迴定義

1.類的遞迴定義

有兩個類這樣定義:


Subject.h 標頭檔案如下:
#ifndef SUBJECT_H
#define SUBJECT_H
#include <iostream>
#include "Observer.h"

class Subject
{
public:
       void Info(){ std::cout <<" Subject !/n"; }
protected:
private:
       Observer myObserver;
};
#endif


Observer.h 標頭檔案如下:
#ifndef OBSERVER_H
#define OBSERVER_H
#include <iostream>

#include "Subject.h"

class Observer
{
public:
       void PrintInfo(){std::cout<<" In Observer !"<<std::endl;}
protected:
private:
       Subject mySubject;
};
#endif
在主檔案中引用這兩個類:
#include <iostream>
using namespace std;
#include "Subject.h"
#include "Observer.h"

int main()
{
       Observer myObser;

       myObser.PrintInfo();

       Subject myS;
       myS.Info();
       return 0;
}

這種情況屬於類的交叉定義。如複雜的觀察者模式中,Subject和Observer要相互註冊到對方。就會出現這種定義。
在這種情況下,編譯是通不過的。
編譯器的提示的錯誤如下:
syntax error : missing '';'' before identifier ''mySubject''
''Subject'' : missing storage-class or type specifiers
''mySubject'' : missing storage-class or type specifiers


錯誤表示找不到類的定義。因為編譯器在為具體的物件分配記憶體時,必要先知道其大小。而上述兩個類遞迴定義,編譯器如何分清物件的大小呢?
我們通過把類的資料成員修改成指標型別,告訴編譯器這個類的大小。並彼此加上類的前向宣告。如下:
Subject.h 標頭檔案如下:
#ifndef SUBJECT_H
#define SUBJECT_H
#include <iostream>
#include "Observer.h"

class Observer;
class Subject
{
public:
       void Info(){ std::cout <<" Subject !/n"; }
protected:
private:
       Observer *     myObserver;
};
#endif

Observer.h 標頭檔案如下:
#ifndef OBSERVER_H
#define OBSERVER_H
#include <iostream>
#include "Subject.h"

class Subject;
class Observer
{
public:
       void PrintInfo(){std::cout<<" In Observer !"<<std::endl;}
protected:
private:
       Subject*  mySubject;
};

事實上,只要打破類宣告的遞迴鏈,就能解決類定義找不到的問題。

2.結構體的遞迴定義


修改如下:


因為程式正確編譯,編譯器必須知道一個結構體所佔用的空間大小