#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
, даже если вы понятия не имеете, что их реализация использует внутри.