Arn*_*sen 6 c++ pimpl-idiom friend inner-classes language-lawyer
我在一些旧的库代码中捣乱,其基本目标是重构它.这个旧代码并不完全符合最佳实践和美观(是的 - 朋友很糟糕,并且在发现下面之后它已被删除 - 因为它是重构的疏忽).
现在准备运行一些单元测试我用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()无法访问第二类的私有成员.在查看了c ++好友规则之后,对我来说,这是正确的 - 但是我对这个错误的理解是什么?我误读了这些信息(英语不是我的第一语言)?
从标准(c ++ 03 - 我现在手头没有c ++ 11):
嵌套类的成员对封闭类的成员没有特殊访问权限,也没有对已经为封闭类授予友谊的类或函数的特殊访问权限.应遵守通常的准入规则(第11条).封闭类的成员对嵌套类的成员没有特殊访问权限; 应遵守通常的准入规则(第11条).
而且这个:
友谊既不是遗传也不是传递.
所以我的基本问题是 - 谁真的是正确的 - clang和gcc还是vc ++?
此外 - 这个问题只是为了对此事的好奇心,并试图更好地了解这个世界.
周围类的成员的可访问性受CWG 45的影响。这意味着,至少部分问题已被归类为 C++98 标准中的缺陷。(似乎2001年就已经提出了解决方案,所以我不太明白为什么它还没有在C++03中修复。)
\n\n在C++11中,合并了该决议,因此该段落已更改为[class.access.nest]/1:
\n\n\n\n\n嵌套类是一个成员,因此具有与任何其他成员相同的访问权限。封闭类的成员对嵌套类的成员没有特殊访问权限;应遵守通常的访问规则。[例子:
\n\nRun Code Online (Sandbox Code Playgroud)\n\nclass E {\n int x;\n class B { };\n\n class I {\n B b; // OK: E::I can access E::B\n int y;\n void f(E* p, int i) {\n p->x = i; // OK: E::I can access E::x\n }\n };\n\n int g(I* p) {\n return p->y; // error: I::y is private\n }\n};\n\xe2\x80\x94结束示例]
\n
(一些)针对缺陷提出的解决方案在编译器中实现;例如,请注意g++ 明确表示该-std=c++03标志意味着
\n\n\n1998 年 ISO C++ 标准加上 2003 年技术勘误表和一些附加缺陷报告。
\n
所以使用这个标志时你得到的结果并不明显。然而,DR 是“委员会意图的指示”,因此它们可以被视为标准中的“错误”,应该予以修复。
\n\nVC++2005 似乎没有按照原始标准实施建议的决议。
\n