C — наследование

#c #inheritance

#c #наследование

Вопрос:

Я ожидал, что следующий фрагмент кода выдаст ошибку компиляции, поскольку у производного класса не будет priv_var того, к которому я пытаюсь получить доступ pub_fun() . Но он скомпилировался, и я получил приведенный ниже результат. Может кто-нибудь объяснить теорию, стоящую за этим?

 class base {

private:
  int priv_var = 90;

public:
  int pub_fun();

} b;

class derived : public base {
} d;

int base::pub_fun() { cout << priv_var << "n"; }

int main() {
  d.pub_fun();
  return 0;
}
 

вывод:

 90
 

Комментарии:

1. Примечание: ваша программа имеет неопределенное поведение, поскольку int base::pub_fun() не возвращает int as объявленный.

Ответ №1:

Он компилируется, поскольку метод pub_fun объявлен в базовом классе. Именно по этой причине он имеет доступ к закрытому члену priv_var . Если бы вы создали метод derived и попытались получить к нему доступ priv_var , вы бы увидели ошибку времени компиляции.

Комментарии:

1. Но я использую объект производного класса ‘d.pub_fun();’. Итак, как решается этот доступ. Я могу понять доступ к priv_var с помощью ‘d.base :: pub_fun ();’ но не с помощью ‘d.pub_fun ();.

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

3. Функция позиционируется в базовом классе, даже если вы используете производный класс. Производный класс может определять свои собственные методы, которые затем будут жить в производном классе, и к ним не будет доступа priv_var . Другими словами, часть вашего экземпляра класса, которая находится в base , имеет доступ к частному пространству base .

4. @moonshines Только virtual функции-члены могут быть переопределены. Метод в производном классе с тем же именем, что и методы в базовом классе, скрывает методы базового класса с этим именем.

5. Если бы вы следовали своей логике, @Mr.Bala, ничего из базового класса не было бы доступно в производном классе. Однако это просто не так, как работает C . В C производный класс расширяет базовый класс, поэтому в нем есть все, начиная с базового, и все, что он предоставляет сверху.

Ответ №2:

1. Класс derived имеет доступ к общедоступным (и защищенным) членам класса base по правилам публичного наследования.

2. Члены класса base имеют доступ ко всем другим base членам, потому что они принадлежат к одному и тому же классу.

d.pub_fun(); допустимо из-за 1. и int base::pub_fun() { cout << priv_var << "n"; } допустимо из-за 2. таким образом, все компилируется и работает без проблем.

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

Здесь вы объединяете два отдельных шага в один. derived Класс действительно не имеет доступа base::priv_var , но derived никогда не пытается использовать base::priv_var . Все, что derived d; нужно сделать, это вызвать общедоступную функцию-член pub_fun() . С этого момента это вопрос pub_fun реализации, о котором derived не нужно знать или заботиться. В вашем примере реализация pub_fun использует закрытую base переменную, что вполне нормально, поскольку это функция-член того же base класса.

В других случаях class derived может быть вашим кодом, а base может быть библиотечным классом, для которого у вас даже нет исходного кода. Вы всегда можете вызывать общедоступные функции-члены из base , даже если вы понятия не имеете, что их реализация использует внутри.