C ++ error: Invalid use of incomplete type ...

I have a small to medium sized project that I am doing for my course in software development this semester. I decided to do it in C ++ (gtkmm). So far, I'm fine, but I had a problem with circular links 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 that in the future they still need to talk to each other. So far, I have come across one specific case, and I tried to solve it myself, but I was completely stuck.

My program has a main window class, which 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_ */ 

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 TCP_IP_Socket class and the login dialog are created in the main window. First, create a connection and set a few lines (see 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 create a login and try to access 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 indicated at the very top of this message. If I remove the class MainWindow; and replace it with #include "MainWindow.h" , I ran into round heading problems.

I know that I posted a lot of code, but I didn’t want me to cry because I didn’t post enough.

+6
c ++
source share
3 answers

You can leave with the MainWindow declaration in Login_Dialog.h until you only send a declaration of the type pointer (which you do), and you add this to the beginning of Login_Dialog.h so that the compiler knows what to expect to see the class declaration in more late 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.

+15
source share

When I try to do this, I get the error presented at the very top of this entry. If I try to remove the MainWindow class; and replace it with #include "MainWindow.h". I run round missions with headings.

But this is a problem. You need to move the implementation to a separate implementation file (.cpp). You can use forward declarations to break circular links in the header files, but before you try to use your type, you must have both headers.

You must include the full definition of your class before you can use it, and not just a declaration. Advanced declarations are only useful for other forward declarations — the compiler needs to know what type it works with before it can generate code.

+1
source share

To fix the error, you must replace #include "Login_Dialog.h" with the next declaration of the Login_Dialog class in Main_Window.h. Then include Login_Dialog.h in Main_Window.cpp and Main_Window.h in Login_Dialog.cpp. BTW, the same can be done for many other files / classes.

0
source share

All Articles