2010-03-06 123 views
6

我有一箇中小型的項目,我正在爲我的軟件工程課程做這個學期。我選擇用C++(gtkmm)來完成它。我做得很好,但迄今爲止我所遇到循環引用或以下錯誤的問題:C++錯誤:不完整類型的使用無效...

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 

總之我有10個班,我知道在未來,他們都將需要談談彼此。到目前爲止,我遇到了一個具體案例,我一直試圖自行解決,但我完全陷入困境。

我的程序有定義了一個主窗口類,如下所示:

/* 
* 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; 
} 

現在主窗口創建一個TCP_IP_Socket類和一個登錄對話框:

/* 
* 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_ */ 

的功能定義如下。我首先創建連接並設置弦數(在下面的代碼所示):

/* 
* 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; 
} 

,然後我創建登錄和嘗試訪問server_ip ustring和server_domainname從我的登錄對話框ustring:

/* 
* 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); 
} 

當我嘗試編譯這個時,我得到了這篇文章最頂部列出的錯誤。如果我刪除class MainWindow;並將其替換爲#include "MainWindow.h",則會遇到帶有標題的循環引用問題。

我知道我發佈了很多代碼,但我不想因爲發佈不夠而發火。

+7

你貼了很多代碼,但是錯過了至關重要的一個.. Login_Dialog。h – Naveen 2010-03-06 05:12:07

回答

15

只要你只將一個指向類型的指針(你會這樣做),並且你將它添加到Login_Dialog.h的頂部,你就可以在Login_Dialog.h中正向聲明MainWindow,這樣編譯器就知道期望稍後再看一個類聲明。

class MainWindow; 

然後在Login_Dialog.cpp中,像這樣包含「mainwindow.h」。

/* 
* Login_Dialog.cpp 
* 
* Created on: Mar 2, 2010 
*  Author: Matthew 
*/ 

#include "Login_Dialog.h" 
#include "MainWindow.h" 

這應該這樣做。

+2

+1更具體 - 更易於理解 - 說出我正在嘗試(和失敗)的方式:P – 2010-03-06 05:16:56

1

When I try and do this I get the error presented at the very top of this post. If I try and remove the class MainWindow; and replace it with #include "MainWindow.h" I run into circular reference issues with headers.

但是,這是問題。您需要將實現移動到單獨的實現(.cpp)文件中。您可以使用前向聲明來打開頭文件中的循環引用,但在嘗試使用類型之前,必須同時使用這兩個頭。

在使用它之前,您必須包含您的類的完整定義 - 而不僅僅是前向聲明。前向聲明只對其他前向聲明有用 - 編譯器在生成代碼之前需要知道它的工作類型。

0

要解決這個錯誤,你應該用Main_Window.h中的Login_Dialog類的前向聲明來替換#include「Login_Dialog.h」。然後在Login_Dialog.cpp中包含Main_Window.cpp中的Login_Dialog.h和Main_Window.h。順便說一句,對於許多其他文件/類也可以做到這一點。

相關問題