указатель базового класса на производный класс в c

#c

#c

Вопрос:

 #include <iostream>
using namespace std;

class A {
    public:
        A ();
        virtual ~A();
};

class B: protected A {
    public:
        virtual ~B ();
};

int main() {
    A* pb = new B;//A is inaccessable base of B
    return 0;
}
  

когда я запускаю приведенный выше код, он сообщает мне, что A является недоступной базой B, pb — это указатель, который указывает на B, в чем проблема?

Ответ №1:

Класс B является производным от класса A, но помечает его как защищенный. Это означает, что только подклассы B «видят», что B является производным от A.

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

Чтобы решить эту проблему, измените ее на это:

 class B: public A {
public:
    virtual ~B ();
};
  

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

1. 1 и просто в дополнение, цитата из стандарта — 11.2.1 ... If a class is declared to be a base class for another class using the protected access specifier, the public and protected members of the base class are accessible as protected members of the derived class ...

2. когда я изменяю его как общедоступный, у него все еще возникают проблемы, тогда он говорит «неопределенная ссылка» на «Base::Base()»

3. @cong — Вы предоставили определение конструктора. A(); это просто объявление.

4. @Mahesh это то, что я хочу спросить, потому что я видел некоторый пример на каком-то веб-сайте, они просто предоставляют объявление конструктора, но без определения, мне было интересно, законно ли это

5. серьезно, это все еще ускользает от меня, в каких случаях кто-то будет использовать защищенное наследование 0_o

Ответ №2:

B защищен от наследования от A, поэтому только подклассы B «знают», что это A. статический main () не «знает» этого, потому что он не наследуется от B.
в этой ситуации вы можете получить доступ к B как к A:

 class C: B {
    void foo() {
        A* pb = new B;
    }
};
  

если вам это нужно в основном, вам нужно было бы изменить B на public, наследовать от A

Ответ №3:

Это потому, что вы унаследовали от A с protected . Измените его на public , и вы получите то, что ожидали.

Смотрите раздел часто задаваемых вопросов по C 24.5 здесь.

Ответ №4:

Проблема заключается в защищенном наследовании. B не является A. У B есть A. Смотрите этот FAQ для получения более подробной информации.

Ответ №5:

Если вы измените

 class B: protected A
  

Для

 class B: public A
  

работает ли это?

Ответ №6:

Проблема в том, что вы наследуете B от A как protected , и поэтому внешнему коду не разрешается «знать», что B наследует от A. Замените protected на public , и код должен скомпилироваться.

Ответ №7:

Производный B от public A , а не protected A :

 class B: public A
{
public:
    virtual ~B ();
};
  

Ответ №8:

Вы используете защищенное наследование. Защищенный, когда применяется к членам, означает, что «производные классы могут получать доступ, но внешние вызывающие устройства не могут». И применительно к наследованию это означает… точно то же самое.

Таким образом, внутри B класса вы знаете, что он является производным от A , и может приводить к A* и обратно

Но вне B (например, в main функции) наследование не видно, и поэтому вы не можете преобразовать B* в A* .

Ответ №9:

Свойство наследования исключает возможность преобразования защищенного родительского класса в подкласс. Следовательно, преобразование атрибутов класса A в класс B на самом деле не произойдет в коде. Если вы не измените protected на public в строке #10 , чтобы соблюдались протоколы, и код не будет выглядеть следующим образом:

 class B: public A
{
public:
    virtual ~B ();
};
  

Ответ №10:

 #include <iostream>

using namespace std;

class A {
    public:
        A () {};
        virtual ~A();
};

class B: public A {
    public:
        B() {};
        virtual ~B ();
};

int main() {
    A* pb = new B;
    return 0;
}
  

Кажется, это работает. В вашем примере вы подготавливаете B к будущему наследованию, protected inherit делает A защищенным, и только методы B могут видеть A.