Всякий раз, когда я получаю новый класс из базового класса, говорите:
#include <iostream>
class A {
protected:
int f;
public:
void get() {
std::cout << "The address is: "<< &f << std::endl;
}
};
class B : public A {
// ....
};
int main() {
A a;
a.get();
B b;
b.get();
return 0;
}
Адрес: 0xbfb0d5b8
Адрес: 0xbfb0d5bc
Означает ли это, что весь код из class A
будет скопирован в class B
? Так как у меня ничего нет в классе B
то есть нет членов или функций данных Итак, когда я создаю экземпляр класса B, я обнаруживаю, что у него есть собственная переменная по другому адресу, а также функция-член. Как у него могут быть свои члены-копии, если они не скопированы?
Это то, что мы подразумеваем под повторное использование кода в наследство?
Обновил мой код, чтобы отразить, что я имел в виду под копированием переменных.
Код никогда не копируется во время наследования. Но когда дочерний объект (класс B) создается или создается во время выполнения, он наследует функциональность и атрибуты родительского класса / объекта (класс A).
код из класса A НЕ копируется в класс B в том смысле, что код написан только в одном месте.
однако, и здесь конусы часть многократного использования, при использовании класса b вы можете вызвать метод и использовать члены, относительно private
, public
и т. д. и, следовательно, не нужно писать один и тот же код для двух классов, которые делают одно и то же
например, если у меня есть круг и квадрат, и у них обоих есть член с именем color, мне нужен метод, который его изменяет, мне не нужно писать метод и член дважды, но они должны наследовать класс Shape, который будет реализовывать один раз, и тогда они оба смогут использовать этот метод, таким образом повторно используя один метод в двух местах
Я не уверен, что «скопировано» является правильным словом (компилятор будет компилировать только код в class A
один раз). Как вы использовали публичное наследство, class B
на самом деле является особый тип class A
, В качестве таких, class B
имеет доступ к каждому (не частному) члену class A
, поэтому код используется повторно.
Кроме того, из разговора в комментариях:
Нет. Ничего не «копируется», каждый экземпляр A и B имеет свое собственное значение для своих собственных переменных, за исключением любых статических элементов данных. Для статических членов данных, опять же, копирование не происходит; существует только одна переменная, которая является общей для всех экземпляров A
а также B
,
В вашем примере вы сравниваете два разных экземпляра двух разных классов. разные экземпляры означают разные базовые адреса для хранения данных экземпляров.
Возможно, лучшим тестом того, копируется ли поле класса в производные классы, является следующее:
#include <iostream>
class A {
protected:
int f;
public:
void get() {
std::cout << "The address is: " << &f << std::endl;
}
};
class B : public A {
// ....
};
int main() {
B b;
b.get();
A *a = &b;
a->get();
return 0;
}
И вывод:
The address is: 0x7fff41d523f0
The address is: 0x7fff41d523f0
С помощью этой программы мы можем видеть, что, хотя у нас есть экземпляр класса B
его унаследованное содержимое физически совпадает с содержимым исходного класса. A
, Обратите внимание, что также возможно переопределить член класса в производном классе, но исходный член все еще будет доступен, если мы приведем экземпляр производного класса к родительскому классу (как я сделал в моем примере).
§1.8 (2) стандарта языка C ++ определяет, что подразумевается под субобъект:
Объекты могут содержать другие объекты, называемые субобъекты. Подобъект может быть подобъект участника (9.2), а подобъект базового класса (Пункт 10) или элемент массива. Объект, который не является подобъектом любого другого объекта, называется завершить объект.
Это примеры дочерних подобъектов и элементов массива, с которыми вы должны быть знакомы:
int a[5];
a[2]; // the third array element subobject of the complete object a
struct S { int x; }
S s;
s.x; // a member subobject of the complete object s
Это оставляет оставшийся вид подобъекта, который вас интересует: подобъекты базового класса.
struct B { int x; }
struct D : public B { int y; }
D d;
d.y; // a member subobject of the complete object d
d.x; // a member subobject of a base class subobject of the complete object d
B &b = d; // a reference to a base class subobject of the complete object d
Каждый экземпляр производного класса содержит экземпляр своего базового класса в качестве подобъекта базового класса.
У меня также есть некоторые сомнения относительно связи между наследованием и повторным использованием кода. Это мой взгляд на это.
Наследование — это механизм, используемый для классификации и облегчения полиморфизма. Используя наследование, мы можем построить иерархию понятий, разделенных по категориям на разных уровнях абстракции. Делая это, мы можем эффективно использовать другую концепцию ООП, полиморфизм, которая позволяет одному и тому же управляющему коду управлять всеми объектами в категории, даже если они отличаются по своей реализации.
Я не думаю, что мы используем наследование для повторного использования кода.