SORU
9 Mart 2009, PAZARTESİ


C dairesel bağımlılıkları gidermek

Ben sık sık kendimi bulmak için bir durum Neredeyim bakan birden çok derleme/linker hataları bir C projesi nedeniyle bazı kötü tasarım kararları (yapılmış başka biri :) ) hangi kurşun dairesel bağımlılıkları arasında C sınıfları farklı başlık dosyaları(ayrıca aynı dosyada olabilir). Ama neyse ki(?) bu yine benim olur Bir dahaki sefere bu sorunun çözümü hatırlamak için genellikle yeterli olmaz. Gelecekte kolay hatırlamak amacıyla temsili bir sorun ve onunla birlikte bir çözüm (bu stackoverflow kurallarına aykırı değildir umarım) post edeceğim. Daha iyi çözümleri-ders bekliyoruz.


  • A.h

    class B;
    class A
    {
        int _val;
        B *_b;
    public:
    
        A(int val)
            :_val(val)
        {
        }
    
        void SetB(B *b)
        {
            _b = b;
            _b->Print(); // COMPILER ERROR: C2027: use of undefined type 'B'
        }
    
        void Print()
        {
            cout<<"Type:A val="<<_val<<endl;
        }
    };
    

  • B.h

    #include "A.h"
    class B
    {
        double _val;
        A* _a;
    public:
    
        B(double val)
            :_val(val)
        {
        }
    
        void SetA(A *a)
        {
            _a = a;
            _a->Print();
        }
    
        void Print()
        {
            cout<<"Type:B val="<<_val<<endl;
        }
    };
    

  • main.cpp

    #include "B.h"
    #include <iostream>
    
    int main(int argc, char* argv[])
    {
        A a(10);
        B b(3.14);
        a.Print();
        a.SetB(&b);
        b.Print();
        b.SetA(&a);
        return 0;
    }
    

CEVAP
9 Mart 2009, PAZARTESİ


Bu olduğunu düşünmek için bir "derleyici" gibi.

Bir derleyici yazma düşünün. Ve bu 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;
}

Bu derleme.ccdosya (unutmayın.ccve değil.hderleme birimi), A nesne için yer tahsis etmek gerekir. Yani, ne kadar alanı? B depolamak için yeterli! B boyutu ne Peki? A depolamak için yeterli! Oops.

Kırmak gerektiğini açıkça döngüsel bir başvuru.

Ara tarafından izin derleyici yerine rezerv alanı olarak biliyor ayarlıyoruz - işaretçiler ve başvurular, örneğin, her zaman 32 veya 64 bit (bağlı olarak mimarlık) ve yerini (herhangi birini) tarafından bir işaretçi veya başvuru, bir şeyler güzel olurdu. Hadi A değiştir dediler

// file: A.h
class A {
  // both these are fine, so are various const versions of the same.
  B& _b_ref;
  B* _b_ptr;
};

Şimdi her şey daha iyi olacak. Biraz. main() yine diyor ki:

// file: main.cc
#include "A.h"  // <-- Houston, we have a problem

Tüm kapsamları ve amaçları ise basit dışarı çıkarırsan () #include sadece dosyayı kopyalar.cc. Yani gerçekten, bu.ccgörünüşe göre:

// file: partially_pre_processed_main.cc
class A {
  B& _b_ref;
  B* _b_ptr;
};
#include "B.h"
int main (...) {
  A a;
}

Derleyici bununla başa çıkamaz. neden görebilirsiniz - B - hiç bu sembolü daha önce hiç görmediği hiç bir fikrin yok.

Hadi B derleyici söyle. Bu ** 36, olarak bilinen ve daha this answer ele alınmıştır.

// main.cc
class B;
#include "A.h"
#include "B.h"
int main (...) {
  A a;
}

Buçalışır. Değilharika. Ama bu noktada "düzeltme kötü de olsa." bunu düzeltmek için ne yaptık döngüsel başvuru sorunu bir anlayış ve olmalıdır

Bu düzeltme kötü olmasının nedeni #include "A.h" yanındaki kişi kullanabilmek B beyan etmek zorunda kalacak ve #include korkunç bir hata. Bu yüzden beyan etmeleri halinde hareket edelimA. hkendisi.

// file: A.h
class B;
class A {
  B* _b; // or any of the other variants.
};

VeB. hbu noktada, sadece 34* *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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • EminemVEVO

    EminemVEVO

    12 Mayıs 2009
  • Māris Zaharovs

    Māris Zahar

    28 Mayıs 2008
  • Tome Rodrigo

    Tome Rodrigo

    9 Temmuz 2006