477 Stimmen

Behebung von Build-Fehlern aufgrund von zirkulären Abhängigkeiten zwischen Klassen

Ich finde mich oft in einer Situation wieder, in der ich mit mehreren Kompilierungs-/Linkerfehlern in einem C++-Projekt konfrontiert bin, die auf einige schlechte Designentscheidungen zurückzuführen sind (die von jemand anderem getroffen wurden :) ), die zu zirkulären Abhängigkeiten zwischen C++-Klassen in verschiedenen Header-Dateien führen (kann auch in derselben Datei vorkommen) . Aber zum Glück(?) passiert das nicht so oft, dass ich mir die Lösung für dieses Problem merken kann, wenn es das nächste Mal wieder auftritt.

Damit Sie sich in Zukunft leicht daran erinnern können, werde ich ein repräsentatives Problem und die dazugehörige Lösung veröffentlichen. Bessere Lösungen sind natürlich willkommen.


  • 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;
    }

0voto

jkoendev Punkte 45

In einigen Fällen ist es möglich definieren. eine Methode oder einen Konstruktor der Klasse B in der Header-Datei der Klasse A, um zirkuläre Abhängigkeiten bei Definitionen aufzulösen. Auf diese Weise können Sie vermeiden, dass Sie Definitionen in .cc Dateien, zum Beispiel wenn Sie eine reine Header-Bibliothek implementieren wollen.

// file: a.h
#include "b.h"
struct A {
  A(const B& b) : _b(b) { }
  B get() { return _b; }
  B _b;
};

// note that the get method of class B is defined in a.h
A B::get() {
  return A(*this);
}

// file: b.h
class A;
struct B {
  // here the get method is only declared
  A get();
};

// file: main.cc
#include "a.h"
int main(...) {
  B b;
  A a = b.get();
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X