Почему преобразование между выведением * на базу * терпит неудачу с частным наследством?

StackOverflow https://stackoverflow.com/questions/3674876

Вопрос

Вот мой код -

#include<iostream>
using namespace std;

class base
{
public:
    void sid()
    {
    }  
};

class derived : private base
{
public:
    void sid()
    {
    }
};

int main()
{
    base * ptr;
    ptr = new derived; // error: 'base' is an inaccessible base of 'derived'
    ptr->sid();
    return 0;
}

Это дает с компиляционной временной ошибкой.

error: 'base' is an inaccessible base of 'derived'

Так как компилятор попытается вызвать базовый класс sid() Почему я получаю эту ошибку? Может кто-нибудь, пожалуйста, объясните это.

Это было полезно?

Решение

$ 11,2 / 4 государства-

Базовый класс B N доступен на R, если

  • изобретенный государственный член B будет государственным членом N, или
  • R встречается у члена или друга класса N, и изобретенный государственный член B будет частным или защищенным членом N, или
  • R встречается у члена или друга класса P, полученного от N, и изобретенный член B будет частным или защищенным членом P, или
  • Существует такое класс, что B - это базовый класс S, доступен на R и S - это базовый класс N доступен в R. »

Здесь «B» является «базой», «N» - «получена», а «R» является главным.

  1. Рассмотрим 2-й пуль - «R встречается у члена или друга класса N, ...». Этот пункт не применяется, так как «R» (Main) не является ни членом, ни другом 'n' (производным)

  2. Рассмотрим 3-й пуль - r встречается у члена или друга класса P .... '. Этот Клаус также не распространяется на те же причины, что и выше

  3. Рассмотрим 4-е пулю - еще раз, этот пункт не применяется

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

$ 11,2 / 5 штатов -

Если доступный класс базового класса можно неявно преобразовать указатель на полученный класс на указатель на этот базовый класс (4.10, 4.11). [Примечание. Из этого следует, что члены и друзья класса X могут косвенно преобразовать X * в указатель на личный или защищенный немедленный базовый класс X.-DENG NOTE

С Base не доступный класс Derived При доступе main, стандартное преобразование от производного класса к базовому классу плохо образуется. Отсюда ошибка.

Редактировать 2:

Изучите сообщения об ошибках некоторых популярных компиляторов, и это должно помочь вам получить лучшее понимание. Обратите внимание, как слово «недоступное» всплывает так часто и последовательно во всех сообщениях об ошибках

Ссылки от проекта стандарта N3000. Мне еще не скачать последний черновик :)

GCC PROG.CPP: в функции «int Main ()»: PROG.cpp: 27: Ошибка: «База» - это недоступная база «выведенного»

Comeau Online «Comeautest.c», Line 26: Ошибка: преобразование в недоступный базовый класс «База» не допускается PTR = New Carived;

VS2010 Ошибка C2243: «Тип литой»: преобразование от «выведенного *» на «базовый *» существует, но недоступна

Другие советы

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

Чусбад предоставил более глубокое объяснение, включающее стандарт, я постараюсь предоставить доступное объяснение.

В C ++ есть 3 спецификатора уровня доступа: public, protected а также private. Отказ Это предназначены для определения того, кто может получить доступ к методам, атрибутам или базовым классам. Это типично среди объектных ориентированных языков.

Здесь вы избрали private наследование. Концептуально это означает, что вы стремитесь скрыть тот факт, что Derived наследует от Base посторонним, что вообще означает, что это детали реализации.

Как следствие, «экстерьер» не знает об этих отношениях. Это применяется компилятором с этим inaccessible сообщение.

С точки зрения дизайна, private наследство обычно не требуется. Либо принцип замены Liskov применяется, и вы используете public Наследование, либо это деталь реализации, и вы используете композицию.

Ты знаешь что class derived наследует от class base, но main() Функция этого не знает. Причина main() Функция не знает, что вы сделали class derived наследовать в частном порядке от class base.

Поэтому, когда вы пытаетесь назначить new derived к ptr, Типы указателей не совместимы.

Попробуй это:

#include<iostream>
#include<conio.h>
using namespace std;

class base
{
      private:
      public:
          virtual void sid() // You might want to declare sid virtual
             {
                  cout<<"base";
             } 
          virtual ~base() // You then probably need a virtual destructor as well.
             {
             } 
};

class derived : public base //public inheritance
{
      private:
      public:
             void sid()
             {
                  cout<<"derived";
             }
};

int main()
{
    base * ptr;
    ptr = new derived;
    ptr->sid();
    getch();
    return 0;
}

Это дает ошибку C2243: «Тип литой»: преобразование от «выведенного *» на «базовый *» существует, но недоступна, этот полученный класс был унаследован в частном порядке .so Объект базового класса не создается при получении полученного создания. Для создания первых вызовов объекта Dreave идет создать объект базового класса, который не происходит. Солстион состоит в том, чтобы вывести класс публично. Это не имеет значения, будь то использование виртуального ключевого слова с функциями элементов или нет.

Вам необходимо объявить свою функцию SID () в базовом классе как виртуальным. Виртуальная функция может быть заменена полученным классом. В противном случае вы, вероятно, получите ошибку компилятора.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top