C ++ Использование объявления, областей объема и доступа

StackOverflow https://stackoverflow.com/questions/2084801

Вопрос

Как правило, объявление «использование» используется для введения в область некоторых функций членов базовых классов, которые в противном случае были бы скрыты. С этой точки зрения это только механизм для предоставления доступной информации более удобной в использовании.
Однако: «Использование» также может использоваться для изменения ограничений доступа (не только для функций, но и для атрибутов). Например:

class C{
public:
  int a;
  void g(){ cout << "C:g()\n"; }
  C() : a(0){}
};

class D : public C{
private:
  using C::a;
  using C::g;
public:
  D() { a = 1; }
};

int main(void){
  D d;
  cout << d.a << endl;  //error: a is inaccessible
  C *cp = &d;
  cout << cp->a << endl; //works
  d.g();  //error: g is inaccessible
  cp->g();  //works
  return 0;
}

Я думаю, что это ограничение доступа в полученном классе на самом деле бесполезно, потому что вы всегда можете получить доступ к g () и a из указателя на базовый класс. Так не должно быть хотя бы какого -то предупреждения компилятора? Или разве не было бы даже лучше запретить такое ограничение доступа производным классом? Использование объявления - не единственная возможность добавить ограничения для доступа. Это также может быть сделано, переопределяя функцию базового класса «размещение ее в разделе с большими ограничениями доступа. Есть ли какие -то разумные примеры, где действительно неплохо ограничить доступ таким образом? Если нет, я не понимаю, почему это должно быть разрешено.

И еще одна вещь: по крайней мере, с G ++, один и тот же код хорошо компилируется без слова «с использованием». Это означает, что для примера выше: можно написать c :: a; и c :: g; вместо использования c :: a; Использование c :: g; Является ли первый только ярлык для последнего или есть некоторые тонкие различия?

//РЕДАКТИРОВАТЬ:
Так что из обсуждения и ответов ниже моего заключения было бы:
- разрешено ограничивать ограничения доступа в полученных классах с публичным наследством
- Есть полезные примеры, где его можно использовать
- Это использование может вызвать проблему в сочетании с шаблонами (например, полученный класс не может быть допустимым параметром для некоторых шаблонов класса/функции.
- Дизайн чистого языка не должен разрешать такое использование
- Компилятор может, по крайней мере, выпустить какое -то предупреждение

Это было полезно?

Решение

Что касается вашего декларации без using: Они называются «объявлениями доступа» и устанавливаются. Вот текст из стандарта, из 11.3/1:

Доступ к члену базового класса может быть изменен в полученном классе, упомянув его квалифицированный идентификатор в декларации полученного класса. Такое упоминание называется декларацией доступа. Эффект объявления доступа qualified-id; определяется как эквивалент декларации usingqualified-id; Сноска: Объявления доступа устарели; член Использование деклараций (7.3.3) обеспечить лучшие средства для выполнения того же. В более ранних версиях языка C ++ объявления доступа были более ограничены; они были обобщены и сделаны эквивалентны Использование деклараций - конечная сноска

Я бы сказал, что чаще всего нехорошо меняться публичный члены частный или же защищенный Участники полученного класса, потому что это нарушит принцип замены: вы знаете, что у базового класса есть некоторые функции, и если вы бросите в полученный класс, тогда вы ожидать Эти функции тоже могут быть вызываемыми, потому что производственный класс это база. И, как вы уже упоминали, этот инвариант уже применяется в любом случае языком, позволяющим конвертировать (который неявно работает!) В ссылку на базовый класс или квалификацию имени функции, а затем вызов (тогда публичная) функция.

Если вы хотите запретить кому -то, что вызывает набор функций базы, то я думаю, что это намекает на то, что сдерживание (или в редких случаях, частное наследование), является лучшей идеей.

Другие советы

В то время как использование объявления, которое вы показали, дает механизм для изменения уровня доступа (но только вниз), это не является основным его использованием в таком контексте. Использование контекста. В основном предназначен для доступа к функциям, которые в противном случае были бы затенены из базового класса из -за языковой механики. Например

class A {
public:
   void A();
   void B();
};

class B {
public:
   using A::B;
   void B(int); //This would shadow A::B if not for a using declaration
};

Декларация

using C::a

приносит «A» в локальный сферу именования, чтобы позже вы могли использовать «A», чтобы судить «c :: a»; С тех пор, как «C :: A» и «A» взаимозаменяемы, если вы не объявляете локальную переменную с именем «A».

Декларация не меняет права доступа; Вы можете получить доступ к «A» в подклассе только потому, что «A» не является частным.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top