在制作我的代码时,我遇到了一个奇怪的问题。我为所有包含1个文件,让我们称之为includes.h和类文件,如clientclass.h等。
问题是,当我尝试编译我的代码时,我得到编译器错误:
/mnt/orange-new/units/includes.h|34|error: 'ClientClass'没有命名类型|
包括:
#ifndef INCLUDES_H_INCLUDED
#define INCLUDES_H_INCLUDED
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <sys/timeb.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <time.h>
#include <iostream>
#include <cstring>
#include <string>
#include "config.h"
#include "console.h"
#include "clientclass.h"
#include "tcpparser.h"
#include "netmsg.h"
#include "main.h"
Console Konsola;
ClientClass Clients;
TCPThread ParserTCP;
#endif // INCLUDES_H_INCLUDED
clientclass.h:
#ifndef CLIENTCLASS_H_INCLUDED
#define CLIENTCLASS_H_INCLUDED
#include "includes.h"
struct ClientStruct {
int Sock;
int Ident;
int Room;
std::string Name;
std::string IP;
};
class ClientClass {
public:
ClientClass(); // create
int Add();
void Delete(int index);
int Count();
ClientStruct Client[MAX_CLIENTS];
protected:
void Reset(int index);
private:
int _count;
};
#endif // CLIENTCLASS_H_INCLUDED
你能帮我解决我的问题吗?我的想法:(
答案 0 :(得分:5)
您有一个循环依赖:includes.h -> clientclass.h -> includes.h
。如何解决这个问题取决于首先包含哪个标题,但它总是会令人困惑。最有可能的是它导致了行
#include <clientclass.h>
成功但未能包含内容,因为即使内容尚不存在,已经定义了包含保护CLIENTCLASS_H_INCLUDED
。
要解决此问题,您可能只能从includes.h
删除clientclass.h
的内容,如果它不用于任何内容。如果使用includes.h
中的类型,则可以使用前向声明,声明类存在而不定义它,例如。
class ClientClass;
通过这种方式,您可以使用ClientClass
的指针和引用,而无需包含clientclass.h
。你不能做的是声明前向声明类型的值,因为编译器必须知道关于类型的所有内容(至少它有多大)才能保留内存的值那种类型。如果你需要这个,你可能需要将标题分成更小的部分,并且只包括你所依赖的小部分。
因此,例如,您可以执行以下操作:
class MyClass;
MyClass * globalPointer;
void doSomething(const MyClass & foobar);
在范围内没有MyClass
的定义。这里的两个表达式仅通过指针或引用使用MyClass
。但以下情况不起作用:
class MyClass;
void doSomethingElse() {
MyClass theobject;
doSomething(theobject);
}
这需要在堆栈上为MyClass
类型的对象保留空间。如果没有范围内MyClass
的定义,编译器无法知道要分配多少内存。
在您的情况下,您要定义ClientClass
类型的全局值,这需要ClientClass
的完整定义,而不仅仅是前向声明。你有几个选择:
ClientClass
另一个选择是重新考虑全局变量是否在这里是正确的解决方案。
答案 1 :(得分:4)
我有点困惑为什么你有一个clientclass.h,其中包括includes.h,其中包括clientclass.h
我认为这个问题可能存在于某个地方。 你不应该这样做。
答案 2 :(得分:0)
也许是因为交叉包括..你是否通过添加
尝试了类型的前向声明class ClientClass;
在includes.h
之前的ClientClass Clients
内
答案 3 :(得分:0)
当您的标题布局时,除了“includes.h”之外的任何地方都不可能包含“clientclass.h”。那是因为在这种情况下,全局实例最终会在“clientclass.h”中定义类之前被声明
如果包含“clientclass.h”,那么它首先要做的是引入“includes.h”,包括用它声明的全局变量。
尝试仅包含“clientclass.h”标题需要:<string>
(以及MAX_CLIENTS
来自的标题)的内容。
答案 4 :(得分:0)
尝试使用前向声明后,我最终得到一个错误:
/mnt/orange-new/units/includes.h|37|error: 聚合'ClientClass客户'有 不完整的类型,不能定义|
编辑: 将includes.h拆分为2个文件classes.h和includes.h解决了这个问题。我非常感谢大家的帮助。在如此低的时间里,我从来没有想到过这么多答案:)期待我更频繁地来到这里。谢谢。