c++ - 将不可访问的私有(private)基类型的指针传递给派生类方法

标签 c++

此代码示例将描述我认为不直观的语言功能。

class A {
public:
  A() {}
};

class B: private A
{
public:
  B() {}
};

class C: public B
{
public:
  C() {}
  void ProcessA(A* a) {
  }
};

int main() {
  C c;
}

在 Mac 上使用 Apple LLVM 4.2 版编译此代码会产生一个

test.cc:16: error: ‘class A’ is inaccessible
test.cc:16: error: within this context

void ProcessA(::A* a) 替换 void ProcessA(A* a) 会使其构建,但我不明白为什么要使用绝对这里的类名。 它是一种语言功能,可以避免某些类型的错误,还是只是一个黑暗的 C++ 语法角落,比如在使用其他模板参数化的模板中的尖括号 (>>) 之间放置空格的要求。 谢谢!

最佳答案

人类谈话

我将首先描述这里发生的事情——如果你已经知道这一点,请原谅我,但它为后续行动创造了必要的背景。

编译器解析不合格的A::C::A (如果您自己在源代码级别进行更改,结果将是相同的)。从 ::C::A无法访问会发出错误消息。

您建议编译器应该检测到 ::C::A无法访问并且对 A 的引用然后应将其视为对 ::A 的引用作为后备。但是,::C::A::A很可能是两个完全不同的东西

在这里自动猜测应该做什么不仅容易引入错误和/或拉扯头发¹,而且完全违背了 C++ 的精神。

标准

直接根据 C++11 标准确认此行为符合设计要求。

§9/2 说:

A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.

这意味着在类 C 的范围内, A是一个注入(inject)的类名

§3.4/3 声明 injected-class-name 是名称查找的候选对象:

The injected-class-name of a class is also considered to be a member of that class for the purposes of name hiding and lookup.

§3.4/1 阐明了基础 A 的不可访问性不会阻止 injected-class-name A从被考虑:

The access rules are considered only once name lookup and function overload resolution (if applicable) have succeeded.

§11.1/5 直接解释了所讨论的确切情况:

[Note: In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the base class in the scope in which it was declared. The injected-class-name might be less accessible than the name of the base class in the scope in which it was declared. —end note ]

标准也给出了这个例子,和你的等价:

class A { };
class B : private A { };
class C : public B {
    A *p;   // error: injected-class-name A is inaccessible
    ::A *q; // OK
};

¹ 想象一下如果 A 会发生什么?最初是 public基数,然后变为 private在重构期间。还可以想象 ::A::C::A是无关的。你会期望像 a->foo() 这样的电话(以前可以工作)会失败,因为 foo不再可访问,而是 a 的类型在你背后发生了变化,你现在得到一个“没有方法foo”的错误。啊?!?这当然远不是可能发生的最坏情况。

关于c++ - 将不可访问的私有(private)基类型的指针传递给派生类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15342410/

相关文章:

当写在一行中时,C++ move 构造函数不使用复合运算符 += 调用

c++ - 为成员对象内联使用非默认显式构造函数

c++ - 为什么 std::cin 字符串输入要求我输入每个空格

c++ - 多线程应用程序概念

java - JNA 在个人电脑上的不同行为

c++ - 继承类的强制转换顺序?

c++ - 是否可以在没有 Visual Studio 的情况下使用 C++ 为 Windows 开发?

c++ - fprintf iofputs.c 上的段错误 : No such file or directory

友元函数的 C++ 内联定义

c++ - eraseFromParent() 错误