Bunu düşünmenin yolu "derleyici gibi düşünmek" tir.
Bir derleyici yazdığınızı düşünün. Ve bunun gibi bir kod görüyorsunuz.
// file: A.h
class A {
B _b;
};
// file: B.h
class B {
A _a;
};
// file main.cc
#include "A.h"
#include "B.h"
int main(...) {
A a;
}
.Cc dosyasını derlerken ( .h'nin değil .cc'nin derleme birimi olduğunu unutmayın ), nesne için alan ayırmanız gerekir A
. Peki, o zaman ne kadar alan var? Saklamak için yeterli B
! O zaman büyüklüğü nedir B
? Saklamak için yeterli A
! Hata.
Kesinlikle kırmanız gereken dairesel bir referans.
Derleyicinin açık işaretçiler ve referanslar hakkında bildiği kadar yer ayırmasına izin vererek onu kırabilirsiniz, örneğin, her zaman 32 veya 64 bit (mimariye bağlı olarak) olacaktır ve bir işaretçi veya referans, işler harika olurdu. Diyelim ki yerini alıyoruz A
:
// file: A.h
class A {
// both these are fine, so are various const versions of the same.
B& _b_ref;
B* _b_ptr;
};
Şimdi işler daha iyi. Biraz. main()
hala diyor ki:
// file: main.cc
#include "A.h" // <-- Houston, we have a problem
#include
, tüm uzantılar ve amaçlar için (önişlemciyi çıkarırsanız) dosyayı yalnızca .cc'ye kopyalar . Gerçekten, .cc şöyle görünür:
// file: partially_pre_processed_main.cc
class A {
B& _b_ref;
B* _b_ptr;
};
#include "B.h"
int main (...) {
A a;
}
Derleyicinin bununla neden başa çıkamayacağını görebilirsiniz - ne B
olduğu hakkında hiçbir fikri yoktur - daha önce hiç sembolü görmemişti.
Derleyiciye anlatalım B
. Bu ileri bir bildiri olarak bilinir ve bu cevapta daha ayrıntılı olarak ele alınmaktadır .
// main.cc
class B;
#include "A.h"
#include "B.h"
int main (...) {
A a;
}
Bu işe yarıyor . O değil harika . Ancak bu noktada, döngüsel referans problemini ve düzeltmeyi kötü de olsa "düzeltmek" için ne yaptığımızı anlamalısınız.
Bu düzeltmenin kötü olmasının nedeni, bir sonraki kişinin kullanmadan önce #include "A.h"
beyan etmesi B
ve korkunç bir #include
hata almasıdır. O halde bildirgeyi Ah'in kendisine taşıyalım .
// file: A.h
class B;
class A {
B* _b; // or any of the other variants.
};
Ve Bh'de , bu noktada, #include "A.h"
doğrudan doğrudan yapabilirsiniz .
// file: B.h
#include "A.h"
class B {
// note that this is cool because the compiler knows by this time
// how much space A will need.
A _a;
}
HTH.