C ++: переопределение публичного \ частного наследования - PullRequest
17 голосов
/ 22 апреля 2011

Если B наследуется от A с использованием public, может ли B переопределить одну из функций и сделать ее закрытой?

class A
{
public:
    virtual double my_func1(int i);
    virtual double my_func2(int i);
}

class B : public A // Notice the public inheritance
{
public:
    virtual double my_func1(int i);
private:
    virtual double my_func2(int i);
}

Как насчет обратного? если тип наследования является закрытым - может ли B заставить определенную функцию быть общедоступной?

Что если A чисто абстрактный? это имеет значение?

Будет ли protected иметь какое-либо значение в любой комбинации?

Ответы [ 5 ]

15 голосов
/ 22 апреля 2011

Если B наследует от A с помощью public, может ли B переопределить одну из функций и сделать ее закрытой? НЕТ

Несмотря на то, что my_func1() объявлен в priavte спецификаторе доступа, он все еще может вызываться через указатель на class A, фактически указывающий на объект class B

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

Конечно, вы не можете напрямую вызывать my_func1() через объект class B, хотя, потому что B::my_func1() объявлено в спецификаторе Private Access, и вы не можете получить доступ к частно объявленным членам вне класса.

Как насчет обратного? если тип наследования является закрытым - может ли B заставить определенную функцию быть открытой?
нет NO

Если вы вызываете my_func1() через указатель Base class A, то во время компиляции он просто оценивается как вызов A::my_func1(), то есть Invalid, поскольку A::my_func1() is declared private in class A`

Что если А чисто чистый? это имеет значение?
нет NO
Не имеет значения, является ли базовый класс абстрактным или просто полиморфным. Будут применяться те же правила.

Имеет ли защищенное значение какое-либо значение в любой комбинации?
нет NO
Как объяснялось в первых 2 Вопросах, если вы вызываете виртуальный указатель на базовый класс, то во время компиляции компилятор проверяет только доступ к этой функции-члену в базовом классе, потому что компилятор видит это как вызов функции-члена базового класса. Фактический вызов функции оценивается в run time, а функция называется Runtime Polymorphism или Dynamic polymorphism, которая не зависит от спецификаторов Access, что является конструкцией времени компиляции.

Итак, в заключение,

переопределение членов базового класса не влияет на доступ

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

Разница

Что если А чисто чистый?это имеет значение?

Единственное отличие, которое он делает, состоит в следующем, то есть как они могут (или не могут) использоваться:

A *pa = new B();
pa->my_func2(10); //calls B::my_func2() even though its private!

B *pb = new B();
pb->my_func2(10); //compilation error - trying to access private function

Объяснение

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

Итак, pa->my_func2() работает, потому что компилятор видит, что статический тип pa равен A*, для которого определена открытая функция my_func2(), поэтому выражение pa->my_func2() проходит тест компилятора.Следовательно, это работает.

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

1 голос
/ 22 апреля 2011

==> If B inherits from A using public, can B override one of the functions and force it to be private?

NO .Указатель / ссылка на A всегда будет видеть my_func2 как общедоступный.Вы все еще можете вызвать этот метод, используя A* или A&.(то, что вы спрашиваете, возможно в Java).

==> if the inheritance type is private - can B force a specific function to be public?

На 1-м месте, если тип наследования является закрытым / защищенным, вы НЕ МОЖЕТЕ назначить объект класса Derived классу Baseуказатель класса / ссылка .например, вы не можете выполнять следующее !!

A* p = new B; // error

==> What if A is pure abstract? does it make a difference?

НЕТ разницы (за исключением того, что вы должны определять методы в B)

==> Would protected make any difference in any combination?

НЕТ разницы (относительно базового класса)

1 голос
/ 22 апреля 2011

То, что вы переопределяете, не влияет на доступ.Таким образом, вы можете создать открытое переопределение приватно унаследованной функции точно так же, как вы создаете закрытое переопределение публично унаследованной функции.

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

0 голосов
/ 17 ноября 2017

Я просматривал сообщения, сделанные другими, и нашел объяснение, связанное с ошибками, возникшими, когда наследование было private/protected в производном классе, несколько запутанным / неполным.

Рассмотрим приведенный ниже фрагмент кода,

class A
{
public:
    virtual double my_func1(int i);
    virtual double my_func2(int i);
}

class B : private A // Notice private inheritance
{
public:
    virtual double my_func1(int i);
private:
    virtual double my_func2(int i);
}

A* ptr = new B; // this is not legal because B has a private base
ptr->my_func1(); // my_func1() is not accessible
ptr->my_func2(); // my_func2() is also not accessible not because it is private but due 
                 // base class A being inherited privately 

Таким образом, когда мы наследуем class B от class A, используя private/protected спецификаторы, это означает, что никто во внешнем мире не знает, что class B унаследовал от class A, следовательно, нельзя присваивать pointer/reference типа class B указатель / ссылка типа class A. Следовательно, доступ к закрытой / защищенной переопределенной виртуальной функции в производных классах действителен только при наследовании в public.

...