C++ error: Invalid use of incomplete type ...
c++
Solution
You can get away with forward declaring MainWindow in Login_Dialog.h as long as you only forward declar a pointer to the type (which you do), and you add this to the top of `Login_Dialog.h` so the compiler knows to expect to see a class declaration at some later time.
class MainWindow;
Then in Login_Dialog.cpp, include "mainwindow.h" like this.
/*
* Login_Dialog.cpp
*
* Created on: Mar 2, 2010
* Author: Matthew
*/
#include "Login_Dialog.h"
#include "MainWindow.h"
That should do it.
Problem
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: ``` 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 ``` 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. My program has a main window class that is defined as follows: ``` /* * 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<Gtk::ActionGroup> m_refActionGroup; RefPtr<Gtk::UIManager> 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_ */ ``` The functions are defined as follows: ``` /* * MainWindow.cpp */ #include "MainWindow.h" MainWindow::MainWindow(int type) { this->socket = new TCP_IP_Socket(this); //Login Section this->login = new Login_Dialog(WINDOW_TOPLEVEL, this); int status; status = this->login->run(); if(status == 0) { exit(1); } this->login->hide(); //By Default Create and Open Up Student Queue this->mdl_Que = new ModelQueue(this); this->view_Que = new ViewQueue(this); this->cntrl_Que = new ControlerQueue(this, (this->mdl_Que), (this->view_Que)); this->set_default_size(1200, 750); this->set_border_width(1); this->set_title("Tutor App"); this->base_VBox = manage(new VBox()); this->main_HBox = manage(new HBox()); this->label_frame = manage(new Frame()); m_refActionGroup = Gtk::ActionGroup::create(); m_refUIManager = Gtk::UIManager::create(); m_refActionGroup->add(Gtk::Action::create("FileMenu", "File")); this->add_accel_group(m_refUIManager->get_accel_group()); Glib::ustring ui_info = "<ui>" "<menubar name='MenuBar'>" " <menu action='FileMenu'>" " </menu>" "</menubar>" "</ui>"; m_refUIManager->insert_action_group(m_refActionGroup); m_refUIManager->add_ui_from_string(ui_info); this->menu = m_refUIManager->get_widget("/MenuBar"); this->mdl_Draw = new ModelDrawing(this); this->view_Draw = new ViewDrawing(this); this->cntrl_Draw = new ControlerDrawing(this, (this->mdl_Draw), (this->view_Draw)); this->mdl_Chat = new ModelChat(this); this->view_Chat = new ViewChat(this); this->cntrl_Chat = new ControlerChat(this, (this->mdl_Chat), (this->view_Chat)); this->status_label = manage(new Label("Welcome to The Tutor App", ALIGN_LEFT, ALIGN_LEFT, false)); //Put it all together this->main_HBox->pack_start(*(this->view_Draw->get_left_VBox())); this->label_frame->add(*(this->status_label)); this->base_VBox->pack_end(*(this->label_frame)); this->main_HBox->pack_end(*(this->view_Chat->get_right_VBox())); this->base_VBox->pack_start(*(this->menu), Gtk::PACK_SHRINK); this->base_VBox->pack_end(*(this->main_HBox), true, true); this->label_frame->set_size_request(-1, 5); this->add(*(this->base_VBox)); this->show_all(); this->view_Que->get_window()->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->view_Que; } ControlerQueue* MainWindow::get_cntrl_Que() { return NULL; } Label* MainWindow::get_status_label() { return this->status_label; } void MainWindow::set_status_label(Glib::ustring label) { this->status_label->set_label(label); } TCP_IP_Socket* MainWindow::get_socket() { return this->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 << "A File|New menu item was selected." << std::endl; } ``` Now the main window creates a `TCP_IP_Socket` class and a login dialog. I first create the connection and set a few strings (seen in the code below): ``` /* * TCP_IP_Socket.cpp */ #include "TCP_IP_Socket.h" TCP_IP_Socket::TCP_IP_Socket(MainWindow* hwnd) { this->hwnd = hwnd; server_name = "www.geoginfo.com"; this->set_server_ustring(this->server_name); printf("%s", this->server_name); struct addrinfo specs; struct addrinfo* results; int status; memset(&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->server_name, NULL, &specs, &results)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); exit(0); } char ipstr[INET6_ADDRSTRLEN]; void* addr; if (results->ai_family == AF_INET) { // IPv4 struct sockaddr_in* ipv4 = (struct sockaddr_in*)results->ai_addr; addr = &(ipv4->sin_addr); } else { // IPv6 struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)results->ai_addr; addr = &(ipv6->sin6_addr); } inet_ntop(results->ai_family, addr, ipstr, sizeof ipstr); this->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->server_domainname = new ustring(server_name); } void TCP_IP_Socket::set_serverip_ustring(const char* ip) { this->server_ip = new ustring(ip); } Glib::ustring* TCP_IP_Socket::get_server_domainname() { return this->server_domainname; } Glib::ustring* TCP_IP_Socket::get_server_ip() { return this->server_ip; } ``` and then I create the login and try to access the `server_ip` ustring and `server_domainname` ustring from my login dialog: ``` /* * Login_Dialog.cpp */ #include "Login_Dialog.h" Login_Dialog::Login_Dialog(int type, MainWindow* hwnd) { this->hwnd = hwnd; this->set_default_size(100, 150); this->user_layout = manage(new HBox()); this->pswd_layout = manage(new HBox()); this->user_name = manage(new Label("Username")); this->user_entry = manage(new Entry()); this->pswd_user = manage(new Label("Password")); this->pswd_entry = manage(new Entry()); this->Ok = add_button("Ok", 1); this->Cancel = add_button("Cancel", 0); Glib::ustring* one = hwnd->get_socket()->get_server_domainname(); this->status_label = manage (new Label("This is a test", ALIGN_LEFT, ALIGN_LEFT, false)); this->Ok->set_size_request(74, -1); this->Cancel->set_size_request(74, -1); this->user_layout->pack_start(*(this->user_name), true, true); this->user_layout->pack_end(*(this->user_entry), true, true); this->pswd_layout->pack_start(*(this->pswd_user), true, true); this->pswd_layout->pack_end(*(this->pswd_entry), true, true); this->get_vbox()->pack_start(*(this->user_layout)); this->get_vbox()->pack_end(*(this->status_label), true, true); this->get_vbox()->pack_end(*(this->pswd_layout)); show_all(); //<-- This is key } void Login_Dialog::set_status_label(Glib::ustring label) { this->status_label->set_label(label); } ``` When I try to compile this I get the error listed at the very top of this post. If I remove `class MainWindow;` and replace it with `#include "MainWindow.h"`, I run into circular reference issues with headers. I know I posted a lot of code, but I didn't want to get flamed for not posting enough.