1

以下是派生类中如何使用基方法的简单示例:

struct Base {
  void foo ();
  Base& operator = (const Base&);
};

struct Derived : Base {
  // ...
};

int main () {
  Derived d1, d2;
  d1.foo();  // calls Base::foo
  d1 = d2;   // calls Base::operator =
}

如果我在正文中添加以下语句Derived以隐藏这两种方法,...

struct Derived : Base {
  //...
private: // hide the below method for `Derived` objects
  using Base::foo;
  using Base::operator =;
}

...然后Base::foo()成功隐藏(变得无法访问)。
Base::operator =仍然可以访问

d1.foo(); // error
d1 = d2;  // ok !!

同样的现象也发生在其他运营商身上。这是一个带有 g++ 的演示

可访问性规则(由于using关键字而应用)不应该以相同的方式应用于方法和运算符吗?
如果不是,那么语句的意义是什么:using operator =;,编译器是否会忽略它?

更新

  1. 我的第一个想法是,编译器可能会生成自己的 default Derived::operator =。这是错误的,因为它使用 Base::operator =.
  2. 如果我使用private继承,则Base::foo()自动隐藏(即使没有using)。但对 没有影响Base::operator =,它仍然有效。

请注意,我不想要“如何隐藏它”的解决方案。但是想从语言的角度理解,为什么运算符不像其他方法那样隐藏。

4

2 回答 2

3

operator=编译器将为Derived 类生成一个默认值,然后隐式Derived::operator=在内部调用Base::operator=
为了摆脱这个,我们需要operator=明确禁用:

struct Derived : Base {
  private: Derived& operator = (const Derived&);  // C++03 way
};

struct Derived : Base {
  Derived& operator = (const Derived&) = delete;  // C++11 way
};
于 2013-07-28T10:55:49.107 回答
1

更新:
我的第一个想法是,编译器可能会生成自己的默认 Derived::operator =。这是错误的,因为它使用Base::operator =. 其他运营商也是如此。

如果我使用私有继承,则Base::foo()自动隐藏(即使不使用)。但对 没有影响Base::operator =,它仍然有效。

你的第一个虽然是正确的。您没有声明复制赋值运算符,因此为您隐式声明了一个。然后您odr -使用了隐式声明的复制赋值运算符,因此编译器提供了隐式定义的复制赋值运算符。结构或类的隐式定义的复制赋值运算符执行类的基类的成员复制赋值,然后是非静态数据成员。

该隐式定义的复制赋值运算符是类成员。通过或通过私有继承将基类复制构造函数隐藏到外部世界并不重要,using因为该基类赋值运算符对这个隐式定义的复制赋值运算符是可见的。

于 2013-07-28T11:25:01.513 回答