2010-03-06 65 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。顺便说一句,对于许多其他文件/类也可以做到这一点。

相关问题