使用“using”声明隐藏基类方法对赋值运算符不起作用

时间:2013-07-28 10:49:56

标签: c++ operator-overloading using language-lawyer method-hiding

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

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 !!

其他运营商也出现了同样的现象。这是一个demo with g++

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

更新

  1. 我的第一个想法是,编译器可能正在生成自己的 默认Derived::operator =。这是错的,因为它使用 Base::operator =
  2. 如果我使用private继承,则会自动Base::foo() 隐藏(即使没有using)。但对Base::operator =没有影响, 它仍然有效。
  3. 请注意,我不想要“如何隐藏它”的解决方案。但是想从语言的角度理解,为什么操作符不像其他方法那样隐藏。

2 个答案:

答案 0 :(得分:3)

编译器将为Derived类生成默认operator=,此隐式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
};

答案 1 :(得分:1)

  

更新:
  我的第一个想法是,编译器可能正在生成它自己的默认Derived :: operator =。这是错误的,因为它使用Base::operator =。同样适用于其他运营商。

     

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

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

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