使用"using"声明隐藏基类方法不适用于赋值运算符

Hiding base class method with "using" declaration doesn't work for assignment operator

本文关键字:不适用 适用于 赋值运算符 类方法 隐藏 using 声明 使用 基类      更新时间:2023-10-16

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

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 =;
}

则成功地隐藏(变得不可访问)CCD_ 2
Base::operator =仍然可访问!!

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

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

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

更新

  1. 我的第一个想法是,编译器可能正在生成自己的默认CCD_ 6。这是错误的,因为它使用Base::operator =
  2. 如果我使用private继承,那么Base::foo()将自动隐藏(即使没有using)。但对CCD_ 11无影响,它仍然有效

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

编译器将为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
};

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

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

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

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

相关文章: