C++ 在朋友类中包含头文件
我想知道你是否必须将“Class1.h”包含在一个将其用作朋友的类中。例如,授予Class1类权限的类的.h文件C++ 在朋友类中包含头文件,c++,class,friend,C++,Class,Friend,我想知道你是否必须将“Class1.h”包含在一个将其用作朋友的类中。例如,授予Class1类权限的类的.h文件 class Class2 { friend class Class1; } 您需要包括“Class1.h”还是不需要?同样在Class2类中,永远不会创建或使用Class1对象。Class1只是操纵Class2,而不是相反。语法是: friend class Class1; 不,你不包括标题 更一般地说,您不需要包含头,除非您实际以某种方式使用了类定义(例如,您使用了类的实
class Class2 {
friend class Class1;
}
您需要包括“Class1.h”还是不需要?同样在Class2类中,永远不会创建或使用Class1对象。Class1只是操纵Class2,而不是相反。语法是:
friend class Class1;
不,你不包括标题
更一般地说,您不需要包含头,除非您实际以某种方式使用了类定义(例如,您使用了类的实例,编译器需要知道其中包含什么)。如果您只是按名称引用该类,例如,您只有一个指向该类实例的指针,并且您正在传递它,那么编译器不需要查看该类定义-通过声明它就足以告诉它关于该类的信息:
class Class1;
这一点很重要,原因有二:次要原因是它允许您定义相互引用的类型(但您不应该这样做!);主要的一点是,它允许您减少代码库中的物理耦合,这有助于减少编译时间
要回答Gary的评论,请注意这可以很好地编译和链接:
class X;
class Y
{
X *x;
};
int main()
{
Y y;
return 0;
}
没有必要提供X的定义,除非您实际使用X中的某些内容。不,您不必“将”Class1.h“包含在将其用作朋友的类中”。您甚至不必向前声明类Class1
的存在。您只需在Class2的定义中将Class1声明为好友,就这样!(我假设friend class Class1
语句本身就是Class1
的一种“转发声明”:
这里有一个完整的、有效的例子。可以(请注意,运行此示例时有两个选项卡——每个文件一个)
Class2.h:
#pragma once
class Class2
{
private:
int _myInt = 123;
// Declare Class1 as a friend class to Class2 so that Class1 can access all of Class2's private
// and protected members (as though Class2's members were part of Class1)
friend class Class1;
};
#include "Class2.h"
#include <stdio.h>
class Class1
{
public:
int getClass2Int()
{
return _class2._myInt;
}
void setClass2Int(int val)
{
_class2._myInt = val;
}
private:
Class2 _class2;
};
int main()
{
printf("Hello World\n");
Class1 class1;
printf("class1.getClass2Int() = %i\n", class1.getClass2Int());
class1.setClass2Int(700);
printf("class1.getClass2Int() = %i\n", class1.getClass2Int());
return 0;
}
main.cpp:
#pragma once
class Class2
{
private:
int _myInt = 123;
// Declare Class1 as a friend class to Class2 so that Class1 can access all of Class2's private
// and protected members (as though Class2's members were part of Class1)
friend class Class1;
};
#include "Class2.h"
#include <stdio.h>
class Class1
{
public:
int getClass2Int()
{
return _class2._myInt;
}
void setClass2Int(int val)
{
_class2._myInt = val;
}
private:
Class2 _class2;
};
int main()
{
printf("Hello World\n");
Class1 class1;
printf("class1.getClass2Int() = %i\n", class1.getClass2Int());
class1.setClass2Int(700);
printf("class1.getClass2Int() = %i\n", class1.getClass2Int());
return 0;
}
#包括“Class2.h”
#包括
一班
{
公众:
int getClass2Int()
{
返回_class2._myInt;
}
void setClass2Int(int val)
{
_类别2._myInt=val;
}
私人:
类别2(u类别2);;
};
int main()
{
printf(“Hello World\n”);
1类;
printf(“class1.getClass2Int()=%i\n”,class1.getClass2Int());
class1.setClass2Int(700);
printf(“class1.getClass2Int()=%i\n”,class1.getClass2Int());
返回0;
}
输出:
你好,世界class1.getClass2Int()=123
class1.getClass2Int()=700 参考资料:
只要类最终包含在同一个二进制文件中(否则在链接过程中会出现错误)@GaryRobinson:只有尝试执行实际需要类定义的操作时,才会出现链接错误。试试看,就像一个想象中的朋友:)我从来没有试过不,这也许是一个很有针对性的理论,但我假设提问者实际上会在某些情况下使用一个friend类way@GabrielStaples如下文所述,我想你可能误解了我所说的“更普遍”的意思——我的意思是还有其他情况,当您将一个类声明为友元时除外,在友元中,您可能同样没有使用类定义,但仍然需要向编译器声明该类。friend声明确实充当了类的声明(您不需要另一个单独的声明),但这不是我想说的重点。我明白了。现在这是有道理的。谢谢。我只是想澄清一下,“更一般地”指的是“即使你没有让班级成为朋友”——也就是说,在你没有使用班级定义的任何情况下,包括这个情况。这并不意味着在声明类为好友时,除了需要转发声明类之外,还需要转发声明类。我明白了。我修改了我的答案,删除了对你答案的提及。我认为我的答案仍然非常有用,可以作为一个完整的例子来说明如何做到这一切。