C++ с помощью объявления, объема и управления доступом

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

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 () и от указателя до базового класса. Так should't там быть по крайней мере некоторым предупреждением компилятора? Или не был бы еще лучше для запрещения такого ограничения доступа производным классом? Объявление использования не является единственной возможностью добавить ограничения к доступу. Это могло также быть сделано через переопределение функции базового класса размещение его в разделе с большим количеством ограничений доступа. Есть ли некоторые разумные примеры, где это действительно nessecary для ограничения доступа таким способом? Если не я не вижу, почему это должно быть позволено.

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

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

11
задан haselhorstk 19 January 2010 в 10:29
поделиться

3 ответа

С учетом Вашего заявления без использования : Они называются "декларациями доступа" и являются устаревшими. Вот текст из стандарта, из 11.3/1:

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

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

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

5
ответ дан 3 December 2019 в 10:44
поделиться

Декларация

using C::a

приносит «А» на локальную область именования, чтобы вы могли позже использовать «A», чтобы отказаться от «C :: A»; Поскольку «C :: A» и «A» взаимозаменяемы, если вы не объявите локальную переменную с именем «A».

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

0
ответ дан 3 December 2019 в 10:44
поделиться

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

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
};
3
ответ дан 3 December 2019 в 10:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: