Tengo un proyecto pequeño o mediano que estoy haciendo para mi curso de ingeniería de software este semestre. He elegido hacerlo en C++ (gtkmm). Estoy haciendo bien hasta ahora, pero se han topado con un problema con referencias circulares o los errores siguientes:Error de C++: uso no válido del tipo incompleto ...
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
En resumen Tengo cerca de 10 clases y sé que en el futuro todos van a tener que hablar con El uno al otro. Hasta ahora me he topado con un caso específico, y he estado tratando de resolverlo por mi cuenta, pero estoy totalmente atascado.
Mi programa tiene una clase de ventana principal que se define como sigue:
/*
* 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_ */
Las funciones se definen como sigue:
/*
* 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;
}
Ahora la ventana principal crea una clase TCP_IP_Socket
y un cuadro de diálogo de inicio de sesión . La primera vez que se crea la conexión y ajuste de algunos hilos (visto en el código de abajo):
/*
* 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;
}
y entonces crear el inicio de sesión y tratar de acceder al server_ip
ustring y server_domainname
ustring de mi diálogo de entrada:
/*
* 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);
}
Cuando intento compilar esto, aparece el error en la parte superior de esta publicación. Si elimino class MainWindow;
y lo reemplazo por #include "MainWindow.h"
, me encuentro con problemas de referencia circulares con encabezados.
Sé que publiqué un montón de código, pero no quería que me llamaran por no publicar lo suficiente.
Ha publicado mucho código, pero ha olvidado el crucial. Login_Dialog.h – Naveen