Действительно ли подклассы наследуют частные переменные-члены?

В принципе, насколько я знаю, когда вы создаете базовый класс с открытым, защищенным и закрытым разделами, а переменные / функции в каждом открытом и защищенном разделах наследуются в соответствующий раздел подкласса (определенный подклассом класса). : частная база, которая возьмет всех публичных и защищенных членов базы и представит их публично, изменив слово «частный» на публичный, сделав их все публичными, а изменив их на «защищенные», сделает их защищенными).

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

Давайте рассмотрим пример:

#include <iostream>

class myClass     // Creates a class titled myClass with a public section and a private section.
{
public:
void setMyVariable();
int getMyVariable();
private:
int myVariable;     // This private member variable should never be inherited.
};

class yourClass : public myClass {};    // Creates a sub-class of myClass that inherits all the public/protected members into  the
// public section of yourClass. This should only inherit setMyVariable()
// and getMyVariable() since myVariable is private. This class does not over-ride any
// functions so it should be using the myClass version upon each call using a yourClass
// object. Correct?

int main()
{
myClass myObject;           // Creates a myClass object called myObject.
yourClass yourObject;       // Creates a yourClass object called yourObject
yourObject.setMyVariable(); // Calls setMyVariable() through yourObject. This in turn calls the myClass version of it    because
// there is no function definition for a yourClass version of this function. This means that this
// can indeed access myVariable, but only the myClass version of it (there isn't a yourClass
// version because myVariable is never inherited).

std::cout << yourObject.getMyVariable() << std::endl;   // Uses the yourClass version of getMyVariable() which in turn
// calls the myClass version, thus it returns the myClass myVariable
// value. yourClass never has a version of myVariable Correct?

std::cout << myObject.getMyVariable() << std::endl;     // Calls the myClass version of getMyVariable() and prints myVariable.

return 0;
}

void myClass::setMyVariable()
{
myVariable = 15;        // Sets myVariable in myClass to 15.
}

int myClass::getMyVariable()
{
return myVariable;      // Returns myVariable from myClass.
}

Теперь, теоретически, основываясь на том, что я думаю, это должно напечатать:
15
15
Из-за этого просто всегда используйте версию функций myClass (таким образом используя myClass myVariable). Но, как ни странно, это не так. Результат выполнения этой программы печатает:
15
0
Это заставляет меня задуматься: неужели мы на самом деле не только наследуем myVariable, но и имеем ли мы возможность возиться с ним? Ясно, что это создает альтернативную версию myVariable, иначе для версии myClass не было бы 0. Мы действительно редактируем вторую копию myVariable, делая все это.

Может кто-нибудь, пожалуйста, объясните мне все это, это разорвало мое понимание наследства.

11

Решение

В принципе, насколько я знаю, когда вы создаете базовый класс с открытым, защищенным и закрытым разделами, а переменные / функции в каждом открытом и защищенном разделах наследуются в соответствующий раздел подкласса (определенный подклассом класса). : частная база, которая будет принимать всех публичных и частных членов базы и помещать их в публичные, изменяя слово «частный» на публичный, делает их всех публичными, а изменяя их на «защищенные», все они становятся защищенными).

В этом утверждении есть некоторая путаница.

Напомним, что наследование определено для классов и структур в C ++. Отдельные объекты (т.е. экземпляры) не наследуются от других объектов. Создание объекта с использованием других объектов называется состав.

Когда класс наследует от другого класса, он получает все от этого класса, но уровень доступа унаследованных полей может препятствовать их использованию в наследнике.

Кроме того, есть 3 вида наследования для классов: private (который используется по умолчанию), protected, а также public, Каждый из них изменяет уровень доступа к свойствам и методам класса, когда наследуется подклассом.

Если мы упорядочим уровни доступа следующим образом: public, protected, privateот наименее защищенного до наиболее защищенного, тогда мы можем определить модификаторы наследования как повышение уровней доступа к наследуемым полям класса по крайней мере до уровня, который они обозначают, в производном классе (т. е. наследование класса).

Например, если класс B наследует от класса A с protected модификатор наследования:

  class B : protected A { /* ... */ };

тогда все поля из A будет иметь по крайней мере protected уровень в B:

  • public поля становятся protected (public уровень повышен до protected),
  • protected поля остаются protected (тот же уровень доступа, так что никаких изменений здесь),
  • private поля остаются private (уровень доступа уже выше модификатора)
20

Другие решения

«Когда вы создаете подкласс, вы никогда не получаете ничего из приватного раздела [базового класса]. Если это так, то у объекта подкласса никогда не должно быть своей собственной версии закрытой переменной или функции из базы класс, правильно?

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

class yourClass : public myClass
{
public:
void playByTheRules()
{
setMyVariable(); // perfectly legal, since setMyVariable() is public
}

void tamperWithMyVariable()
{
myVariable = 20; // this is illegal and will cause a compile-time error
}
};
9

myObject а также yourObject два разных объекта! Зачем им что-то делить?

Подумайте об этом так: забудьте о наследовании и предположим, что у вас есть класс Person с private int age; а также public void setAge (int age) {...}, Затем вы создаете два объекта:

Person bob;
Person bill;
bob.setAge(35);

Вы ожидаете, что Биллу сейчас тоже будет 35? Вы бы не стали, верно? Точно так же ваш myObject не делится своими данными с yourObject,


В ответ на ваш комментарий:

Класс yourClass наследуется от myClass, Это означает, что оба yourObject а также myObject есть свои myVariableпоследний явно по определению, первый унаследован от myClass,

7

Физически каждый отдельный член (включая функции-члены) базового класса входит в подкласс. Не имеет значения, если они являются частными. Не имеет значения, если вы наследуете их публично / защищенно / конфиденциально. Итак, в вашем примере yourClass содержит все три getMyVariable(), setMyVariable() а также myVariable, Все это довольно просто, хорошо?

Важно то, как мы можем получить к ним доступ. Это как когда файл удаляется в вашей системе. Итак, вы должны сначала понять разницу между участником, который не находится там, и участником, который находится там, но недоступен. Предположим сейчас, что все наследование происходит публично. Затем все открытые члены базового класса являются общедоступными в производном классе, защищенные члены защищены, а частные члены недоступны. Они недоступны и не существуют, потому что в защищенном и общедоступном разделах базового класса могут быть некоторые функции-члены, которые обращаются к закрытым членам базового класса. Таким образом, нам нужны все те частные члены базы, к которым имеют доступ открытые и защищенные функции-члены базы, для их функциональности. Поскольку мы не можем простым способом определить, какой член нужен для какой функции-члена, мы включаем все закрытые члены базового класса в производный класс. Все это просто означает, что в производном классе закрытый член может быть изменен только через функции-члены базового класса.

Примечание: доступ к каждому приватному члену, прямо или косвенно, [через другую приватную функцию-член, которая в свою очередь вызывается публичной / защищенной функцией-членом] через публичную / защищенную функцию meber, в противном случае он бесполезен.

Итак, мы знаем до сих пор, что закрытая переменная-член базового класса используется в производном классе, т. Е. Для функциональности ее открытых / защищенных функций-членов. Но они не могут быть доступны непосредственно в базовом классе.

Теперь обратим наше внимание на частное / публичное наследование. Для публичного наследования это означает, что все доступные члены базового класса (то есть публичные и защищенные члены) не могут быть на уровне более разрешающем, чем публичные. Поскольку публика является наиболее разрешающим уровнем, публичные и защищенные члены остаются публичными. Но при защищенном и частном наследовании оба становятся защищенными и частными в производном классе, соответственно. В последнем случае, поскольку все эти члены являются частными, к ним нельзя получить дальнейший доступ в цепочке иерархии, но все равно они могут быть доступны для данного производного класса.

Таким образом, уровень каждого члена базового класса в производном классе является меньшим по сравнению с их уровнем в производном классе () и типом наследования (публичное / защищенное / частное).

То же самое относится и к функциям вне класса. Для них частные и защищенные члены недоступны, но они существуют и могут быть доступны через публичные функции-члены.

И принимая ваше дело в качестве последнего примера, setMyvariable() а также getMyVariable() может получить доступ myVariable в производном классе. Но ни одна функция, указанная в производном классе, не может получить доступ myVariable, Изменение вашего класса:

class myClass
{
public:
void setMyVariable();
int getMyVariable();
private:
int myVariable;
};

class yourClass : public myClass
{
public:
// void yourFunction() { myVariable = 1; }
/*Removing comment creates error; derived class functions can't access myVariable*/
};

Далее: вы также можете добавить исключения к типу наследования, например, частное наследство, за исключением члена, обнародованного в производном классе. Но это совсем другой вопрос.

6

Ты никогда не звонишь myObject.setMyVariable(), так myObject.getMyVariable() не вернется 15.

private не подразумевает static,

5

После:

class yourClass : public myClass {};

есть только одна переменная-член. Но есть два способа доступа к нему по имени: myClass::myVariable, а также yourClass::myVariable,

В этих выражениях имя класса известно как класс именования. Вторая ключевая вещь, которую нужно понять, это то, что права доступа применяются к комбинации именования класса и имени члена; не только к имени члена и не к самой переменной.

Если член упоминается без явного присутствия класса именования, то класс именования выводится из типа выражения слева от . или же -> который назвал член (с this-> подразумевается, если нет такого выражения).

Кроме того, существует четыре возможных типа доступа: public, protected, private, а также нет доступа. Вы не можете объявить участника как имеющего нет доступа, но такая ситуация возникает, когда частный член наследуется.


Применяя всю эту теорию к вашему примеру:

  • Имя myClass::myVariable является private,
  • Имя yourClass::myVariable является нет доступа.

Повторим, на самом деле существует только одна переменная, но она может быть названа двумя разными способами, и права доступа различаются в зависимости от того, какое имя используется.


Наконец, вернемся к исходному примеру. myObject а также yourObject это разные объекты. Я думаю, что то, что вы намеревались написать, или то, что вы мысленно представляете, на самом деле это ситуация:

yourClass yourObject;
myClass& myObject = yourObject;
//    ^^^

что значит myObject называет часть базового класса yourObject, Затем после:

yourObject.setMyVariable();

переменная установлена ​​в 15, так что

std::cout << myObject.getMyVariable() << std::endl;

будет выводить 15 потому что действительно есть только одна переменная.

0

Это может помочь

#include<iostream>
using namespace std;

class A
{
int b;
};

class B : private A
{

};

int main()
{
C obj;
cout<<sizeof(obj);
return 0;
}
-1
По вопросам рекламы [email protected]