title: C++ error: Invalid use of incomplete type ...
body: <p>I have a small- to medium-size project that I am doing for my software engineering course this semester. I have chosen to do it in C++ (gtkmm). I am doing okay so far but I have run into a problem with circular references or the following errors:</p>
  
  <pre><code>Login_Dialog.cpp:25: error: invalid use of incomplete type ‘struct MainWindow’
  Login_Dialog.h:12: error: forward declaration of ‘struct MainWindow’
  make: *** [Login_Dialog.o] Error 1
  </code></pre>
  
  <p>In short I have about 10 classes and I know in the future they are all going to need to talk to each other. I have run into one specific case so far, and I have been trying to resolve it on my own, but I am totally stuck.</p>
  
  <p>My program has a main window class that is defined as follows:</p>
  
  <pre><code>/*
   * MainWindow.h
   */
  
  #ifndef MAINWINDOW_H_
  #define MAINWINDOW_H_
  
  #include "includes.h"
  
  #include "ModelDrawing.h"
  #include "ViewDrawing.h"
  #include "ControlerDrawing.h"
  #include "ModelChat.h"
  #include "ViewChat.h"
  #include "ControlerChat.h"
  #include "ModelQueue.h"
  #include "ViewQueue.h"
  #include "ControlerQueue.h"
  #include "Login_Dialog.h"
  #include "TCP_IP_Socket.h"
  
  class MainWindow : public Window
  {
  public:
   MainWindow(int type);
   ~MainWindow();
  
   void on_menu_file_new_generic();
   void on_menu_file_quit();
  
   ModelDrawing* get_mdl_Draw();
   ViewDrawing* get_view_Draw();
   ControlerDrawing* get_cntrl_Draw();
  
   ModelChat* get_mdl_Chat();
   ViewChat* get_view_Chat();
   ControlerChat* get_cntrl_Chat();
  
   ModelQueue* get_mdl_Que();
   ViewQueue* get_view_Que();
   ControlerQueue* get_cntrl_Que();
  
   Label* get_status_label();
  
   void set_status_label(Glib::ustring label);
  
   TCP_IP_Socket* get_socket();
  
  private:
   TCP_IP_Socket* socket;
  
   Widget* menu;
   RefPtr&lt;Gtk::ActionGroup&gt; m_refActionGroup;
   RefPtr&lt;Gtk::UIManager&gt; m_refUIManager;
  
   ModelDrawing* mdl_Draw;
   ViewDrawing* view_Draw;
   ControlerDrawing* cntrl_Draw;
  
   ModelChat* mdl_Chat;
   ViewChat* view_Chat;
   ControlerChat* cntrl_Chat;
  
   ModelQueue* mdl_Que;
   ViewQueue* view_Que;
   ControlerQueue* cntrl_Que;
  
   Frame* label_frame;
   Label* status_label;
  
   Login_Dialog* login;
  protected:
   //Containers
   HBox* main_HBox;
   VBox* base_VBox;
  };
  
  #endif /* MAINWINDOW_H_ */
  </code></pre>
  
  <p>The functions are defined as follows:</p>
  
  <pre><code>/*
   * MainWindow.cpp
   */
  
  #include "MainWindow.h"
  
  MainWindow::MainWindow(int type)
  {
   this-&gt;socket = new TCP_IP_Socket(this);
  
   //Login Section
   this-&gt;login = new Login_Dialog(WINDOW_TOPLEVEL, this);
   int status;
   status = this-&gt;login-&gt;run();
   if(status == 0)
   {
    exit(1);
   }
   this-&gt;login-&gt;hide();
  
   //By Default Create and Open Up Student Queue
   this-&gt;mdl_Que = new ModelQueue(this);
   this-&gt;view_Que = new ViewQueue(this);
   this-&gt;cntrl_Que = new ControlerQueue(this, (this-&gt;mdl_Que), (this-&gt;view_Que));
  
   this-&gt;set_default_size(1200, 750);
   this-&gt;set_border_width(1);
   this-&gt;set_title("Tutor App");
  
   this-&gt;base_VBox = manage(new VBox());
   this-&gt;main_HBox = manage(new HBox());
   this-&gt;label_frame = manage(new Frame());
  
   m_refActionGroup = Gtk::ActionGroup::create();
   m_refUIManager = Gtk::UIManager::create();
   m_refActionGroup-&gt;add(Gtk::Action::create("FileMenu", "File"));
   this-&gt;add_accel_group(m_refUIManager-&gt;get_accel_group());
   Glib::ustring ui_info =
   "&lt;ui&gt;"
   "&lt;menubar name='MenuBar'&gt;"
   " &lt;menu action='FileMenu'&gt;"
   " &lt;/menu&gt;"
   "&lt;/menubar&gt;"
   "&lt;/ui&gt;";
   m_refUIManager-&gt;insert_action_group(m_refActionGroup);
   m_refUIManager-&gt;add_ui_from_string(ui_info);
   this-&gt;menu = m_refUIManager-&gt;get_widget("/MenuBar");
  
   this-&gt;mdl_Draw = new ModelDrawing(this);
   this-&gt;view_Draw = new ViewDrawing(this);
   this-&gt;cntrl_Draw = new ControlerDrawing(this, (this-&gt;mdl_Draw), (this-&gt;view_Draw));
  
   this-&gt;mdl_Chat = new ModelChat(this);
   this-&gt;view_Chat = new ViewChat(this);
   this-&gt;cntrl_Chat = new ControlerChat(this, (this-&gt;mdl_Chat), (this-&gt;view_Chat));
  
   this-&gt;status_label = manage(new Label("Welcome to The Tutor App", ALIGN_LEFT, ALIGN_LEFT, false));
  
   //Put it all together
   this-&gt;main_HBox-&gt;pack_start(*(this-&gt;view_Draw-&gt;get_left_VBox()));
   this-&gt;label_frame-&gt;add(*(this-&gt;status_label));
   this-&gt;base_VBox-&gt;pack_end(*(this-&gt;label_frame));
   this-&gt;main_HBox-&gt;pack_end(*(this-&gt;view_Chat-&gt;get_right_VBox()));
   this-&gt;base_VBox-&gt;pack_start(*(this-&gt;menu), Gtk::PACK_SHRINK);
   this-&gt;base_VBox-&gt;pack_end(*(this-&gt;main_HBox), true, true);
  
   this-&gt;label_frame-&gt;set_size_request(-1, 5);
  
   this-&gt;add(*(this-&gt;base_VBox));
   this-&gt;show_all();
   this-&gt;view_Que-&gt;get_window()-&gt;show_all();
  }
  
  MainWindow::~MainWindow()
  {
  }
  
  ModelDrawing* MainWindow::get_mdl_Draw()
  {
   return NULL;
  }
  
  ViewDrawing* MainWindow::get_view_Draw()
  {
   return NULL;
  }
  
  ControlerDrawing* MainWindow::get_cntrl_Draw()
  {
   return NULL;
  }
  
  ModelChat* MainWindow::get_mdl_Chat()
  {
   return NULL;
  }
  
  ViewChat* MainWindow::get_view_Chat()
  {
   return NULL;
  }
  
  ControlerChat* MainWindow::get_cntrl_Chat()
  {
   return NULL;
  }
  
  ModelQueue* MainWindow::get_mdl_Que()
  {
   return NULL;
  }
  
  ViewQueue* MainWindow::get_view_Que()
  {
   return this-&gt;view_Que;
  }
  
  ControlerQueue* MainWindow::get_cntrl_Que()
  {
   return NULL;
  }
  
  Label* MainWindow::get_status_label()
  {
   return this-&gt;status_label;
  }
  
  void MainWindow::set_status_label(Glib::ustring label)
  {
   this-&gt;status_label-&gt;set_label(label);
  }
  
  TCP_IP_Socket* MainWindow::get_socket()
  {
      return this-&gt;socket;
  }
  
  void MainWindow::on_menu_file_quit()
  {
   hide(); //Closes the main window to stop the Gtk::Main::run().
  }
  
  void MainWindow::on_menu_file_new_generic()
  {
     std::cout &lt;&lt; "A File|New menu item was selected." &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>Now the main window creates a <code>TCP_IP_Socket</code> class and a login dialog. I first create the connection and set a few strings (seen in the code below):</p>
  
  <pre><code>/*
   *  TCP_IP_Socket.cpp
   */
  
  #include "TCP_IP_Socket.h"
  
  TCP_IP_Socket::TCP_IP_Socket(MainWindow* hwnd)
  {
   this-&gt;hwnd = hwnd;
  
      server_name = "www.geoginfo.com";
      this-&gt;set_server_ustring(this-&gt;server_name);
      printf("%s", this-&gt;server_name);
  
   struct addrinfo specs;
   struct addrinfo* results;
   int status;
  
   memset(&amp;specs, 0, sizeof specs);
   specs.ai_flags = 0;
   specs.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
   specs.ai_socktype = SOCK_STREAM;
  
   if ((status = getaddrinfo(this-&gt;server_name, NULL, &amp;specs, &amp;results)) != 0)
   {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
    exit(0);
   }
  
      char ipstr[INET6_ADDRSTRLEN];
   void* addr;
      if (results-&gt;ai_family == AF_INET)
   { // IPv4
    struct sockaddr_in* ipv4 = (struct sockaddr_in*)results-&gt;ai_addr;
    addr = &amp;(ipv4-&gt;sin_addr);
   }
   else
   { // IPv6
    struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)results-&gt;ai_addr;
    addr = &amp;(ipv6-&gt;sin6_addr);
   }
   inet_ntop(results-&gt;ai_family, addr, ipstr, sizeof ipstr);
   this-&gt;set_serverip_ustring(ipstr);
   printf(" = %s\n", ipstr);
   freeaddrinfo(results); // free the linked list
   printf("\n");
  }
  
  
  TCP_IP_Socket::~TCP_IP_Socket()
  {
  }
  
  void TCP_IP_Socket::set_server_ustring(const char* server_name)
  {
      this-&gt;server_domainname = new ustring(server_name);
  }
  
  void TCP_IP_Socket::set_serverip_ustring(const char* ip)
  {
      this-&gt;server_ip = new ustring(ip);
  }
  
  Glib::ustring* TCP_IP_Socket::get_server_domainname()
  {
      return this-&gt;server_domainname;
  }
  
  Glib::ustring* TCP_IP_Socket::get_server_ip()
  {
      return this-&gt;server_ip;
  }
  </code></pre>
  
  <p>and then I create the login and try to access the <code>server_ip</code> ustring and <code>server_domainname</code> ustring from my login dialog:</p>
  
  <pre><code>/*
   * Login_Dialog.cpp
   */
  
  #include "Login_Dialog.h"
  
  Login_Dialog::Login_Dialog(int type, MainWindow* hwnd)
  {
   this-&gt;hwnd = hwnd;
   this-&gt;set_default_size(100, 150);
  
   this-&gt;user_layout = manage(new HBox());
   this-&gt;pswd_layout = manage(new HBox());
  
   this-&gt;user_name = manage(new Label("Username"));
   this-&gt;user_entry = manage(new Entry());
   this-&gt;pswd_user = manage(new Label("Password"));
   this-&gt;pswd_entry = manage(new Entry());
   this-&gt;Ok = add_button("Ok", 1);
   this-&gt;Cancel = add_button("Cancel", 0);
  
   Glib::ustring* one = hwnd-&gt;get_socket()-&gt;get_server_domainname();
   this-&gt;status_label = manage (new Label("This is a test", ALIGN_LEFT, ALIGN_LEFT, false));
  
   this-&gt;Ok-&gt;set_size_request(74, -1);
   this-&gt;Cancel-&gt;set_size_request(74, -1);
  
   this-&gt;user_layout-&gt;pack_start(*(this-&gt;user_name), true, true);
   this-&gt;user_layout-&gt;pack_end(*(this-&gt;user_entry), true, true);
   this-&gt;pswd_layout-&gt;pack_start(*(this-&gt;pswd_user), true, true);
   this-&gt;pswd_layout-&gt;pack_end(*(this-&gt;pswd_entry), true, true);
   this-&gt;get_vbox()-&gt;pack_start(*(this-&gt;user_layout));
   this-&gt;get_vbox()-&gt;pack_end(*(this-&gt;status_label), true, true);
   this-&gt;get_vbox()-&gt;pack_end(*(this-&gt;pswd_layout));
  
   show_all(); //&lt;-- This is key
  }
  
  void Login_Dialog::set_status_label(Glib::ustring label)
  {
   this-&gt;status_label-&gt;set_label(label);
  }
  </code></pre>
  
  <p>When I try to compile this I get the error listed at the very top of this post. If I remove <code>class MainWindow;</code> and replace it with <code>#include "MainWindow.h"</code>, I run into circular reference issues with headers. </p>
  
  <p>I know I posted a lot of code, but I didn't want to get flamed for not posting enough.</p>