C ++错误:无效使用不完整的类型... [英] C++ error: Invalid use of incomplete type ...

查看:162
本文介绍了C ++错误:无效使用不完整的类型...的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个中小型项目,我在这个学期为我的软件工程课程做。我选择在C ++(gtkmm)。我到目前为止,但我遇到了一个问题与循环引用或以下错误:

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

总之,我有约10个班,我知道在将来他们都需要彼此交谈。我已经遇到了一个特定的情况,到目前为止,我一直在努力解决它,我自己,但我完全卡住。

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

函数定义如下:

/*
 * 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 类和登录对话框。我首先创建连接并设置几个字符串(见下面的代码):

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

然后我创建登录并尝试访问 server_ip ustring和 server_domainname ustring从我的登录对话框:

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

当我尝试编译这个错误时,这个帖子。如果我删除 class MainWindow; 并替换为 #includeMainWindow.h,我遇到循环引用问题带标题。

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.

推荐答案

你可以逃避在Login_Dialog.h中向前声明MainWindow,只要你转发一个指向类型的指针(你做的),并将它添加到顶部 Login_Dialog.h ,因此编译器知道以后会看到类声明。

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;

然后在Login_Dialog.cpp中包含mainwindow.h。

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"

应该这样做。

这篇关于C ++错误:无效使用不完整的类型...的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆