我正在尝试使用开源项目。最新官方(来自* .tar.gz文件)和前沿(来自SVN存储库)版本的内容如下:
class Type1 {
friend class Ridiculous;
friend class Number;
friend class Of_Friends;
int ImportantPrivateSemiSharedData;
};
// In another header...
class Ridiculous {
class Inner {
void MyFunc( Type1 &t )
{ /*do something with t.ImportantPrivateSemiSharedData*/ }
};
};
AFAIK,将class A
标记为friend
class B
,不会提供与A
friend
发货权相关联的任何类型与B
。从[{1}}派生的类和A
friend
A
的{{1}}类friend
都不会附带B
。我认为这种限制也适用于内部类。
我正在使用2002年的一台计算机卡住了几个操作系统版本,而该程序(可能是它的设计团队)主要是在新的计算机上。我的系统编译器是旧的和破坏的,还是新热点的编译器允许他们不应该做的事情?这是C ++ 11的变化吗?
我只是想使用这个程序,但我一直陷入这样的困境。我已经怀疑了,因为代码中充满了各种各样的技术,比如“拥有大量朋友的私人数据”和“无处不在的内部类”,我认为这些代码气味。团队正在一起使用这些技术,但我认为它们基本上是不兼容的,因为friend
船没有结转,你不能前向声明内部类。
(如果需要,我使用的是Mac OS X Tiger 10.4.11 / PowerPC 32位(配备G4的eMac)。该程序是LLVM和CLang(以及LLVM测试套件),试用v3来自Subversion的.0档案和r153311。编译器是Apple提供的带XCode 2.5的GCC 4.0.1。)
看到第一个回复,现在我怀疑将一个班级标记为朋友有两种解释。如果class A
中包含friend class X
,则该声明可以授予对以下内容的访问权:
static
。X
或特殊或两者都没有)
X
作为前缀。我认为我的编译器使用第一个定义,而编写器的编译器使用第二个定义。是否有正式的解释是正确的?如果是这样,规范何时发生(C ++ 98/03,缺陷报告,C ++ 11)?我一直认为友谊意味着第一个版本(包括我读过的C ++材料);直到现在,第二个从未进入我的脑海。
答案 0 :(得分:1)
我认为这里有两个问题。一个是代码闻起来很糟糕,正如你所说,第二个是它不能在你的系统上编译。关于气味,是的,过度使用friend
关键字通常表示不良的OO设计。通常情况下,给对象提供完成工作所需的内容而不是从中提取一些东西,这实际上就是friend
允许你做的事情。
大量的内部类,IMO,并不是那么糟糕,因为它们只是用于将类保持在另一个类的范围内。这有助于保持命名空间不那么混乱,并允许您在不同的功能区域中使用通用名称。
关于编译问题,我试图在我的系统上重现这个问题(Ubuntu 10.04,gcc 4.4.3,此时已有两年了),并创建了这个示例程序:
class A
{
friend class B;
int x;
};
class B
{
class Inner
{
public:
void foo(A& a)
{
a.x++;
}
};
public:
void bbb()
{
Inner i;
A a;
i.foo(a);
}
};
int main()
{
B b;
b.bbb();
}
编译时没有错误或警告。我最初没有标记为public,但我需要添加bbb()
来创建类Inner
的实例,我必须添加Inner
的公共方法,以便我可以调用它来执行有A
的东西。
结果是我认为你的开发系统已经过时了。主要的开发人员显然没有编译代码的问题,因此差异必须与您的系统有关,否则他们已经以他们没有告诉您的方式配置他们的系统。话虽这么说,我认为他们可以做更多的事情来使他们的代码更便携,更容易构建。在开源项目中,如果您希望其他人贡献,那就是预期的。