Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 嵌套类和可见性范围的继承_C++_Inheritance_Nested Class - Fatal编程技术网

C++ 嵌套类和可见性范围的继承

C++ 嵌套类和可见性范围的继承,c++,inheritance,nested-class,C++,Inheritance,Nested Class,考虑以下代码: 名称空间基{ 阶级基础{ 受保护的: 类嵌套{ 受保护的: 基地*基地; 公众: 嵌套(基*_基):基(_基){} 虚空试验(){ base->foo(); /* *嗯,我们可以使用受保护的方法 */ 基础->杆(); } }; 受保护的: 嵌套*嵌套; 无效条(){} 公众: void foo(){} 虚空试验(){ 嵌套=新嵌套(此); 嵌套->测试(); } }; }; 命名空间继承{ 类基:公共基::基{ 公众: Base() :base::base(){} 受保护的:

考虑以下代码:

名称空间基{
阶级基础{
受保护的:
类嵌套{
受保护的:
基地*基地;
公众:
嵌套(基*_基):基(_基){}
虚空试验(){
base->foo();
/*
*嗯,我们可以使用受保护的方法
*/
基础->杆();
}
};
受保护的:
嵌套*嵌套;
无效条(){}
公众:
void foo(){}
虚空试验(){
嵌套=新嵌套(此);
嵌套->测试();
}
};
};
命名空间继承{
类基:公共基::基{
公众:
Base()
:base::base(){}
受保护的:
嵌套类:公共基::基::嵌套{
公众:
嵌套(继承的::Base*Base)
:base::base::Nested(base){}
公众:
虚空试验(){
base->foo();
/*
*嗯..现在他们无法访问
*/
//基础->杆();
}
};
公众:
虚空试验(){
foo();
bar();
嵌套=新嵌套(此);
嵌套->测试();
}
};
};
我的问题是为什么我们可以从
base::base::Nested
访问
base::base
的受保护方法/属性,但无法从
inherited::base::Nested
访问
inherited::base
的相同方法/属性


我唯一可以假设的是
base::base
base::base::Nested
的一种全局作用域,因此它们是可访问的
inherited::Base
inherited::Base::Nested
的一种全局作用域,
Base::Base
的受保护成员不可访问。但是,公共继承不应改变可见性的范围,我不清楚无法访问的原因。

问题似乎是存储指针的类型,而不是访问权限。考虑这一点:

class B {
protected:
  void bar();
};

class D : public B {
public:
  void call() {
    this->bar(); // works
    static_cast<B*>(this)->bar(); // does not work
  }
};
B类{
受保护的:
空心钢筋();
};
D类:公共B类{
公众:
无效调用(){
此->条();//有效
静态_cast(this)->bar();//不起作用
}
};
当您试图通过 存储在基址中的指针


您可以通过向下转换base来解决此问题,但我强烈反对。

§11.4/1在访问受保护的成员(我突出显示了相关部分)时有这样的说法:

如前所述,当非静态数据成员或非静态成员函数是其命名类(11.2)的受保护成员时,将应用第11条所述之外的附加访问检查,授予对受保护成员的访问权是因为引用发生在某个C类的朋友或成员中。如果访问要形成指向成员的指针(5.3.1),则嵌套名称规范应表示C或从C派生的类。所有其他访问都涉及(可能隐式)对象表达式(5.2.5)在这种情况下,对象表达式的类应为C或从C派生的类。

这不容易理解。谢天谢地,该标准给出了许多示例来说明其含义,其中一个似乎正是您的情况(除非我误解了代码中的某些内容,这是很有可能的):

(注意,为了简单起见,我删除了示例中不相关的部分,并重命名了一些元素。)

换句话说,在

pb->i = 1;
成员
i
是通过
pb
找到的,它是指向基类的指针,因此命名类是
B
。但是访问发生在
mem()
,它是
D
的成员
B
D
不同,也不是从中派生的(虽然
D
是从
B
派生的),因此不允许访问

但是在

i = 3

该成员是通过
找到的,因此命名类是
D
,并且允许访问。

您的思维方式非常奇怪。继承::基?好的,不管怎样,为了这个例子的目的,去掉80%的代码,创建Base、BaseNested、Derived和DerivedNested类,去掉所有没有说明问题的函数。请尽量避免代码中不必要的错误(名称空间,太多的成员),并使其可编译(没有奇怪的未定义宏,没有丢失的包含)。否则,这是一个好问题。是否有任何理由认为这不是的副本?最终我得到了它。我正试图从
继承的::base::Nested::test()
访问受保护的方法
base::base::Nested::bar()(和
inherited::Base::Nested::Base
)是
Base::Base
类型的指针,而不是
inherited::Base
类型的指针。现在我很清楚了。@ilardm请参考jogojapan的答案以获得相关的标准引号。这种行为似乎不直观,但却是必要的,因此访问限制不能轻易规避。
i = 3