【发布时间】:2024-04-12 15:00:02
【问题描述】:
我在一些旧的库代码中胡闹,基本目标是重构它。这段旧代码并不完全符合最佳实践和美感(是的 - 朋友很糟糕,并且在发现以下内容后已将其删除 - 因为它是重构中的疏忽)。
现在准备运行一些单元测试,我用 clang++、g++ 和 vc++ 编译了代码(2005 - 是的,我知道它很旧,但为了向后兼容 - 我必须这样做)。
g++和clang++编译运行没有错误,但是Visual C++报错,所以看了代码后,我发现了这样的效果:
#include <iostream>
class one {
private:
struct private_impl;
private_impl* pimpl_;
public:
one();
~one();
void say_hello();
};
class two {
private:
friend class one;
void say_world();
public:
};
struct one::private_impl {
two t;
void say_world();
};
void one::private_impl::say_world() {
std::cout << " ";
t.say_world(); //This should not work should it?
}
one::one() : pimpl_(new private_impl) { }
one::~one() {
delete pimpl_;
}
void one::say_hello() {
std::cout << "Hello";
pimpl_->say_world();
std::cout << std::endl;
}
void two::say_world() {
std::cout << "World";
}
int main() {
one test;
test.say_hello();
return 0;
}
使用开关编译(g++ 和 clang++):
-Wall -Wextra -pedantic
clang++ version: 3.3
g++ version: 4.8.2
现在 Visual C++ 抱怨 private_impl::say_world() 无法访问类 2 的私有成员。在查看 c++ 朋友规则后对我来说,这是正确的 - 但我对此的理解是错误的吗?我是否误读了信息(英语不是我的第一语言)?
从标准(c++03 - 我现在手头没有 c++11):
嵌套类的成员对 封闭类,也不是授予友谊的类或函数 到封闭类;应遵守通常的访问规则(第 11 条)。 封闭类的成员对 嵌套类;应遵守通常的访问规则(第 11 条)。
还有这个:
友谊既不是遗传的也不是传递的。
所以我的基本问题是——谁是正确的——clang 和 gcc 还是 vc++?
另外 - 这个问题只是出于对此事的好奇,并试图更好地了解这个世界。
【问题讨论】:
-
有趣的是,这在 C++11 中发生了变化:“嵌套类是一个成员,因此具有与任何其他成员相同的访问权限。”在下面的例子中,第一条评论是
// OK: E::I can access E::B -
这已被归类为 C++03 中的缺陷,请参阅CWG 45,所以一切都是“正确的”! (至少,DR 是关于类似的东西,并且建议的解决方案也会影响您的情况。)g++ 和 clang++ 已经实现了针对缺陷的建议(并且在 C++11 中接受)解决方案,而 VC++2005 没有。
-
@dyp 感谢您提供的信息 - 我搜索了此信息,但结果为空(我的谷歌搜索技能似乎变弱了)。无论如何 - 有趣的是,使用 -std=c++03 使用 g++ 进行编译,上面的代码仍然有效 - 但猜测它已被视为标准中的缺陷,它是追溯实现的。发表您的评论作为答案,我会接受。
-
@dyp 作为答案发布,我没有机会循环引用 C++03 引用,否则我会更早发布答案 ;-)跨度>
标签: c++ inner-classes friend language-lawyer pimpl-idiom