Виртуальная функция, нарушающая частный доступ - PullRequest
2 голосов
/ 16 апреля 2011

Недавно я наткнулся на эту статью на сайте IBM . Ниже приведен пример кода

#include "iostream"

class B {
public:
  virtual void f()
  {
    std::cout<<"\n In class B";
  }
};

class D : public B {
private:
    int i;

  void f()
  {
  std::cout<<"\n In class D i = "<<i;
  }
  public:
    D(int i_num):i(i_num)
    {}
};

int main() {
  D dobj(10);
  B* bptr = &dobj;
  D* dptr = &dobj;

  // valid, virtual B::f() is public,
  // D::f() is called
  bptr->f();

  // error, D::f() is private
  //dptr->f();
}

Теперь мы можем вызывать частную функцию D. Я хотел бы знать, не нарушает ли это инкапсуляцию C ++?

P.S. Пожалуйста, перейдите в раздел Доступ к виртуальной функции в Виртуальной функции. Я не знаю, почему я не получаю точную ссылку при вставке.

Ответы [ 3 ]

6 голосов
/ 16 апреля 2011

Вызов bptr->f() оценивается во время выполнения в зависимости от типа объекта, на который указывает bptr. Во время компиляции компиляция видит вызов bptr->f() как вызов B::f(), и, поскольку B::f() равен public, компилятор не сообщает только об ошибке. Только во время выполнения оценивается фактический вызов функции D::f().

Это не нарушает принцип Encapsulation, это особенность C ++, называемая Run-time Polymorphism или Dynamic Polymorphism

Вы не можете напрямую вызвать dptr->f(), потому что D::f() объявлен в Private Спецификатор доступа, и Вы не можете получить доступ к частно объявленным членам вне класса.

2 голосов
/ 16 апреля 2011

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

Так что bptr->f() работает, потому что компилятор видит, что статический тип bptr равен B с функцией public f() определено, поэтому выражение bptr->f() проходит тест компилятора.Следовательно, это работает.

Но dptr->f() не работает, поскольку статический тип dptr равен D, который имеет закрытую функцию f(), поэтому код не будетдаже не компилировать!

Теперь, нарушает ли это инкапсуляцию или нет, это очень субъективный вопрос и получит субъективные ответы.Это полностью зависит от того, как его определить, и от него напрямую вытекают аргументы.Не существует единого универсального определения.Мое личное мнение таково: если язык позволяет это, то (это подразумевало бы), согласно сообществу C ++, это не нарушает инкапсуляцию, или, если это так, то C ++ позволяет это достигать чего-то очень благородного (что в противном случаене возможно).В противном случае, я бы сказал, что это просто еще одна ошибка C ++, такая как:

Аргумент по умолчанию в середине списка параметров?

2 голосов
/ 16 апреля 2011

Это по замыслу.

B :: f публично.Доступ пользователя f через указатель на B разрешен.Поскольку f является виртуальным, вызов будет отправлен производным классам ' f .

Но D :: f является частным, вы можетеДоступ к f через указатель do D .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...