我有两个类,Mesh和MeshList。我希望MeshList具有可以更改Mesh的私有成员的函数。但它不会编译,我不知道为什么。这是我的代码。
Mesh.h
#ifndef _MESH_H
#define _MESH_H
#include "MeshList.h"
#include <iostream>
class Mesh
{
private:
unsigned int vboHandle_;
friend void MeshList::UpdateVBOHandle();
public:
inline void Out() {std::cout << vboHandle_;}
};
#endif
Mesh.cpp
#include "Mesh.h"
MeshList.h
#ifndef _MESH_LIST_H
#define _MESH_LIST_H
#include "Mesh.h"
class MeshList
{
public:
Mesh *mesh; //Line 11 Error
void UpdateVBOHandle();
};
#endif
MeshList.cpp
#include "MeshList.h"
void MeshList::UpdateVBOHandle()
{
*mesh->vboHandle_ = 4;
}
我收到这些错误:
MeshList.h(第11行)
错误C4430:缺少类型说明符 - 假定为int。注意:C ++没有 支持default-int
mesh.h(11):错误C2653:'MeshList':不是类或命名空间 名称
答案 0 :(得分:9)
汇编Mesh.cpp
时,它包含Mesh.h
,其中包含MeshList.h
,其中包含Mesh.h
但由于_MESH_H
现已定义而提前停止。然后(回到MeshList.h
)有一个对Mesh
的引用 - 但尚未声明。因此,例如,您的C2143错误。
答案 1 :(得分:6)
这是因为您在#include "MeshList.h"
文件中Mesh.h
,因此将首先编译文件MeshList.h
,并且尚未声明类Mesh
。为此,编译器会认为错误行中的Mesh
是一个在它之前没有类型的变量名,因此就是错误。
这是制作friend
成员函数的示例:
#include <iostream>
class foo;
class bar
{
public:
void barfunc(foo &f);
};
class foo
{
private:
friend void bar::barfunc(foo &f);
int i;
public:
foo()
{
i = 0;
}
void printi()
{
std::cout << i << '\n';
}
};
void bar::barfunc(foo &f)
{
f.i = 5;
}
int main()
{
foo f;
bar b;
b.barfunc(f);
f.printi();
return 0;
}
答案 2 :(得分:6)
在其他答案中解释了循环依赖...
解决方案来了:
在MeshList.h
:
#include "Mesh.h"
替换class Mesh;
(此处不需要包含,因为您只声明指向网格的指针)在MeshList.cpp
:
#include "Mesh.h"
添加到您的包含(您需要声明,因为您使用网格)你提到的最后一个编译错误是另一个问题:
*mesh->vboHandle_ = 4;
mesh
是一个指针。您的代码选择成员vboHandle_
并尝试取消引用它(失败)。我想你的意思是:
mesh->vboHandle_ = 4; // <-- no leading asterisk
答案 3 :(得分:4)
问题:您的包含中的循环依赖项。不幸的是,错误消息不太理想。
解决方案:如果你是整个班级的朋友,而不是单一的函数,那么你可以使用类的前向声明来打破循环。
// Mesh.h
#ifndef _MESH_H
#define _MESH_H
#include <iostream>
class MeshList;
class Mesh
{
private:
unsigned int vboHandle_;
friend class MeshList;
public:
inline void Out() {std::cout << vboHandle_;}
};
#endif
一些(主观)指导原则:
以相反顺序包含内容,如果它中断,则更改它,即:STL优先,第三方标题第二,您自己的中间件堆栈第三,当前项目包括第四,当前库包括第五。这样,如果存在冲突,希望错误将指向您的标题。
将public
内容放在课程中的private
内容之前。该类的客户端只关注公共接口,不需要让它们在所有脏的实现细节之前进行处理。