forward type declarations



  • Hallo allerseits,

    ich habe hier zwei Klassen die sich gegenseitig bedingen. Das löste ich bisher mit forward type declarations. Damit konnte ich pointer der jeweils anderen Klassen speichern.

    Jetzt will ich aber auch über die Pointer auf Methoden der jeweils anderen Klasse zugreifen. Geht das oder muss ich das Design umstellen?

    Gruß



  • goran schrieb:

    Jetzt will ich aber auch über die Pointer auf Methoden der jeweils anderen Klasse zugreifen. Geht das oder muss ich das Design umstellen?

    In der Sourcedatei kannst du durchaus den jeweils Header einbinden, und dann auch über die Zeiger zugreifen.



  • Ich hab' mir mal die Mühe gemacht mein Problem zurecht zu stutzen:

    B.hpp:

    #ifndef B
    #define B
    
    #include <string>
    #include <vector>
    
    class A
    
    class B
    {
    public:
      void add_a(A* a)
      {
        as_.push_back(a);
      }
    
      const std::string& get_content()
      {
        content_.clear();
        for(int i=0, j=as_.size(); i<j; ++i)
        {
          content_ += "  " + as_.at(i)->get_content() + "\n";
        }
        return content_;
      }
    
    private:
      std::string content_;
      std::vector<A*> as_;
    };
    
    #endif
    

    A.hpp

    #ifndef A
    #define A
    
    #include <string>
    #include <vector>
    
    #include "B.hpp"
    
    class A
    {
    public:
      const std::string& get_content()
      {
        content_.clear();
        for(int i=0, j=bs_.size(); i<j; ++i)
        {
          content_ += bs_.at(i).get_content() + "\n";
        }
        return content_;
      }
    
      void add_b(B* b)
      {
        bs_.push_back(b);
      }
    private:
      std::string content_;
      std::vector<B*> bs_;
    };
    
    #endif
    

    test.cc

    #include <iostream>
    
    #include "B.hpp"
    #include "A.hpp"
    
    int
    main()
    {
      A* a = new A();
      B* b = new B();
    
      B->add_a(a);
      std::cout << b->get_content();
    
      delete B;
      delete A;
    }
    

    Das Bsp. kompiliert natürlich nicht. Woher soll der Compiler wissen was er in Zeile 22 von B.hpp machen soll? Ich weiß es auch nicht 🤡

    Beide Klassen haben jeweils eine Methode die gleich heißen: "get_content" Hätten auch heißen können: "do_some_stuff"
    Aber diese Methoden sind das Problem. Beide Klassen wollen von der jeweils anderen eine Methode aufrufen.

    Was machen 😕

    Gruß


  • Mod

    goran schrieb:

    Beide Klassen haben jeweils eine Methode die gleich heißen: "get_content" Hätten auch heißen können: "do_some_stuff"
    Aber diese Methoden sind das Problem. Beide Klassen wollen von der jeweils anderen eine Methode aufrufen.

    Was machen 😕

    Du kannst nicht beide gleichzeitig inline in der Klassendefinition definieren, weil sie von der Definition der jeweils anderen Klasse abhängen -> wenigstens eine der beiden Funktionen muss außerhalb ihrer Klasse definiert werden, z.B. B.hpp

    #ifndef B_HPP
    #define B_HPP
    
    #include <string>
    #include <vector>
    
    class A
    
    class B
    {
    public:
      void add_a(A* a)
      {
        as_.push_back(a);
      }
    
      const std::string& get_content();
    
    private:
      std::string content_;
      std::vector<A*> as_;
    };
    // --- hier könnte auch die .cc -Datei anfangen
    // nicht vorher, weil die include-Direktive in A.hpp dank include-Guards unwirksam ist, wenn A.hpp von B.hpp aus inkludiert wird
    #include <A.hpp>
    inline const std::string& A::get_content()
    {
    ...
    


  • Ich hab's nochmal überarbeitet:

    B.hpp:

    #ifndef B_HPP_
    #define B_HPP_
    
    #include <string>
    #include <vector>
    
    class A;
    
    class B
    {
    public:
      void add_a(A* a);
      const std::string& get_content();
    private:
      std::string content_;
      std::vector<A*> as_;
    };
    
    #endif
    

    B.cc:

    #include "A.hpp"
    #include "B.hpp"
    
    void
    B::
    add_a(A* a)
    {
      as_.push_back(a);
    }
    
    const std::string&
    B::
    get_content()
    {
      content_.clear();
      for(int i=0, j=as_.size(); i<j; ++i)
      {
        content_ += "  " + as_.at(i)->get_content() + "\n";
      }
      return content_;
    }
    

    A.hpp:

    #ifndef A_HPP_
    #define A_HPP_
    
    #include <string>
    #include <vector>
    
    #include "B.hpp"
    
    class A
    {
    public:
      const std::string& get_content();
      void add_b(B* b);
    private:
      std::string content_;
      std::vector<B*> bs_;
    };
    
    #endif
    

    A.cc

    #include "A.hpp"
    
    const std::string&
    A::
    get_content()
    {
      content_.clear();
      for(int i=0, j=bs_.size(); i<j; ++i)
      {
        content_ += bs_.at(i)->get_content() + "\n";
      }
      return content_;
    }
    
    void
    A::
    add_b(B* b)
    {
      bs_.push_back(b);
    }
    

    main.cc:

    #include <iostream>
    #include "B.hpp"
    #include "A.hpp"
    
    int
    main()
    {
      A* a = new A();
      B* b = new B();
    
      b->add_a(a);
      std::cout << b->get_content();
    
      delete b;
      delete a;
    }
    

    Jetzt kompiliert er (g++) aber der Linker weigert sich:
    (edit: jetzt doch)

    g++ A.cc B.cc main.cc
    


  • Du musst die anderen Quelldateien auch noch angeben:

    g++ A.cc B.cc main.cc
    

    In deinem Falle empfehle ich auch noch den Beitrag hier.



  • Autsch, Tippfehler in A.cc und - viel schlimmer - dem Compiler A.cc nicht mitgegeben. 🤡

    Hab's oben korrigiert. Jetzt geht's.


Anmelden zum Antworten