【问题标题】:"using" with base class name to change access valid?“使用”与基类名称更改访问是否有效?
【发布时间】:2013-07-12 14:18:40
【问题描述】:

我的朋友给我看了下面的代码

struct A {
  virtual void f() = 0;
  virtual void g() = 0;
};

struct AInternal : A {
  virtual void f() { /* ... */ }
  virtual void g() { /* ... */ }
};

他使用AInternal 作为实现大部分(如果不是全部A)的内部类。然后他从AInternal 继承,但由于他希望AInternal 保持不可访问状态(因为它是一个实现细节),所以他继承了protected(根据of 实现)。他还做了usinging 基类名称以使A 可访问(默认情况下它受到保护,因为AInternal 也被继承保护)

struct C : protected AInternal {
  using AInternal::A;
};

实际上,这很好用(但正如我们后来发现的那样,它仍然保留了成员函数private - 只是基类被制作了public),但它只适用于GCC。它无法使基础A 可访问。任何想法?我们甚至可以破解在 Clang 上运行的代码

struct C : public AInternal {
protected:
  using AInternal::A;
};

C *c = 0;
A *a = c; // error on GCC!

有人可以帮忙吗?

【问题讨论】:

  • 如果我做对了,那么 A 定义了由 C 提供的接口。我实际上不明白的是整个设置背后的想法。如果A 中不存在,它会使AInternal 中的公共方法无法访问,但可以在AInternal 中将此类方法设为私有并在C 中继承公共方法。
  • @Pixelchemist 的想法是让using AInternal::A 再次公开成员函数。这不起作用,但它确实 所做的是使基类A 可访问。
  • 是的,但我不明白这种布局的原因。为什么不在AInternal 中公开接口方法,使用公共继承就可以了?诸如辅助函数或其他成员之类的“实现细节”仍然可以在 AInternal 中私有。
  • @ainternal 他希望只保护中产阶级。我想更好的方法是为 AInternal 类做一个 using 声明。但这失败了,因为它将是一个继承的构造函数声明。

标签: c++ using-declaration


【解决方案1】:

您只会影响注入的类名的可见性。基础子对象或其成员的访问保护不应受到影响。如果 Clang 或 GCC 允许它影响基础内的强制转换有效性或访问,那是他们的错误。

[class.member.lookup] 10.2/3 说

在声明集中,使用声明被它们指定的成员替换,类型声明(包括注入的类名)被它们指定的类型替换。

基类子对象在成员查找中没有名称;注入的类名确实如此。

【讨论】:

  • 好吧,说到魔鬼。我刚刚在自己的代码中遇到了一个案例,我错误地认为注入的类型名称与引入它的基类具有相同的访问资格。事实证明,如果你真的依赖它,最好明确定义自己的盐渍名称,或者使用特征成语。
  • 谢谢!我对这一切一无所知,并且由于基类的可见性而开始睡不好觉。 +1
猜你喜欢
  • 2012-09-05
  • 1970-01-01
  • 2014-03-18
  • 1970-01-01
  • 2019-05-25
  • 2014-01-04
  • 2011-05-20
  • 2023-03-19
  • 2012-09-05
相关资源
最近更新 更多