C++ 类转发声明失败
我有两个头文件和一个源文件 食物.h:C++ 类转发声明失败,c++,C++,我有两个头文件和一个源文件 食物.h: #ifndef _FOOD_H #define _FOOD_H struct food { char name[10]; }; #endif 狗。h: #ifndef _DOG_H #define _DOG_H class food; //forward declaration class Dog { public: Dog(food f); private: food _f; }; #endif 这是类狗的源文件
#ifndef _FOOD_H
#define _FOOD_H
struct food {
char name[10];
};
#endif
狗。h:
#ifndef _DOG_H
#define _DOG_H
class food; //forward declaration
class Dog {
public:
Dog(food f);
private:
food _f;
};
#endif
这是类狗的源文件
//dog.cpp
#include "dog.h"
#include "food.h"
Dog::Dog(food f) : _f(f)
{}
问题是我可以编译上面的代码,我得到一个错误,说\u f的类型不完整
我想我可以在
dog.h
中提出声明,并在dog.cpp
中包含food.h
,但它不起作用,为什么?我不应该把用户定义的头文件放在.h
文件中,对吗?它已经被弃用了,不是吗?编译器需要知道对象的大小\u f
,而仅使用正向声明无法访问该对象。如果您使用指向类食物的指针
,这将起作用,但由于您的成员是完整的类实例,您需要包含标题,以便编译器可以知道类食物的大小
类似地,如果继承自食品类
,则转发声明将不起作用-您将特别需要包含标题
只需删除转发声明并包含“food.h”,您的代码就会编译。编译器需要知道仅使用转发声明无法访问的对象的大小。如果您使用指向
类食物的指针
,这将起作用,但由于您的成员是完整的类实例,您需要包含标题,以便编译器可以知道类食物的大小
类似地,如果继承自食品类
,则转发声明将不起作用-您将特别需要包含标题
只需删除转发声明并包含“food.h”,您的代码就会编译。转发声明在这种情况下不起作用,因为您的
Dog
类有一个food
的实例。编译器需要完整声明食物
,才能声明狗
至于反对包含的问题,除非我误解了什么,否则它根本不是真的。在这里添加food.h
可以解决您的问题:
//dog.h
#ifndef DOG_H
#define DOG_H
#include "food.h";
class Dog {
public:
Dog(food f);
private:
food f_;
};
转发声明在这种情况下不起作用,因为您的
Dog
类有一个food
实例。编译器需要完整声明食物
,才能声明狗
至于反对包含的问题,除非我误解了什么,否则它根本不是真的。在这里添加food.h
可以解决您的问题:
//dog.h
#ifndef DOG_H
#define DOG_H
#include "food.h";
class Dog {
public:
Dog(food f);
private:
food f_;
};
将“food.h”包含在您的
dog.h
中。这是必要的,一点也不反对。旁注:你不应该在include guarders(\ifndef\u FOOD\u H…
)中使用前导下划线,因为它在某些上下文中是保留的,所以只要使用\ifndef FOOD\u H…
@LokiAstari,即使有FOOD
数据成员?@KerrekSB,但是有人告诉我,如果一个用户定义的文件被更改,那么在其他头中包含用户定义的头可能会增加编译时间。如果您通过引用传递食物(并且成员是引用),那么编译器不需要知道大小,因此转发声明将起作用。否则它需要知道大小,因此您需要在使用前包含头文件。将#include“food.h”
放入您的dog.h
。这是必要的,一点也不反对。旁注:你不应该在include guarders(\ifndef\u FOOD\u H…
)中使用前导下划线,因为它在某些上下文中是保留的,所以只要使用\ifndef FOOD\u H…
@LokiAstari,即使有FOOD
数据成员?@KerrekSB,但是有人告诉我,如果一个用户定义的文件被更改,那么在其他头中包含用户定义的头可能会增加编译时间。如果您通过引用传递食物(并且成员是引用),那么编译器不需要知道大小,因此转发声明将起作用。否则它需要知道大小,因此您需要在使用前包含头文件。是的,包含food.h
可以解决问题,但是如果包含的文件被更改,则包含用户定义的头文件可能包括编译时间,对吗?@Alcott确实如此。如果您在food.h
中更改了某些内容,那么依赖它的所有代码都必须重新编译。最好尽量减少包含,并尽可能使用前向声明,但在这种情况下不能(除非您更改Dog
,使其不包含food
实例)。老实说,我不太理解编译器在声明类Dog
时是如何工作的。我想它会先把dog.h
展开成dog.cpp
,然后开始解释类dog
的定义,如果那样的话,它应该知道food
是什么样子的,因为我在dog.cpp
@mikeseymour中包含了food.h
,定义中的尾随下划线有问题吗?我以为只为实现保留了前导下划线。@Alcott头提供了编译时代码客户机所需的一组信息。这包括函数和类声明。类中包含的类的完整声明是必需的信息之一。是的,包括food.h
可以解决问题,但是如果包含的文件被更改,包括用户定义的头可能包括编译时,对吗?@Alcott确实如此。如果您在food.h
中更改了某些内容,那么依赖它的所有代码都必须重新编译。最好尽量减少包含,并尽可能使用前向声明,但在这种情况下不能(除非您更改Dog
,使其不包含food
实例)。老实说,我不太理解编译器在声明类Dog
时是如何工作的。我以为它会先展开dog.h
到