Скрытие метода базового класса с использованием «quot; объявление не работает для оператора присваивания

Ниже приведен простой пример того, как базовые методы доступны в производном классе:

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. Моя первая мысль была о том, что компилятор может генерировать свои собственные
    дефолт Derived::operator =, Это неправильно, потому что он использует
    Base::operator =,
  2. Если я использую private наследство, то Base::foo() автоматически
    скрытый (даже без using). Но не влияет на Base::operator =,
    это все еще работает.

Обратите внимание, что я не хочу, чтобы решение «как это скрыть». Но хотелось бы понять с языковой точки зрения, почему операторы не скрыты как другие методы.

1

Решение

Компилятор сгенерирует значение по умолчанию 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
};
3

Другие решения

Обновить:
Моей первой мыслью было, что компилятор может генерировать свой собственный Derived :: operator = по умолчанию. Это неправильно, потому что он использует Base::operator =, То же самое относится и к другим операторам.

Если я использую частное наследство, то Base::foo() автоматически скрывается (даже без использования). Но не влияет на Base::operator =, это все еще работает.

Ваш первый хотя был правильным. Вы не объявили оператор присваивания копии, поэтому он был объявлен неявно для вас. Ты тогда ODR-использовал этот неявно объявленный оператор присваивания копии, поэтому компилятор предоставил неявно определенный оператор присваивания копии. Неявно определенный оператор присваивания копии структуры или класса выполняет пошаговое присваивание копии базовых классов класса, а затем его нестатических членов-данных.

Этот неявно определенный оператор присваивания копии является членом класса. Неважно, что вы спрятали конструктор копирования базового класса во внешний мир через using или посредством частного наследования, потому что этот оператор присваивания базового класса видим для этого неявно определенного оператора присваивания копии.

1

По вопросам рекламы [email protected]