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

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

Вот мой код -

#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(), почему я могу получить эту ошибку? Может кто-то объяснит это.

4b9b3361

Ответ 1

$11.2/4 состояния -

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

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

Здесь "B" является "базой", "N" является "производным", а "R" является основным.

  • Рассмотрим вторую пулю: "R встречается у члена или друга класса N,...". Этот пункт не применяется, поскольку "R" (main) не является ни членом, ни другом "N" (Derived)

  • Рассмотрим 3-ю пулю: "R встречается у члена или друга класса P....". Этот раздел также не применяется по тем же причинам, что и выше.

  • Рассмотрим 4-ю пулю. Еще раз это предложение не применяется.

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

$11.2/5 состояний -

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

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

ИЗМЕНИТЬ 2:

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

Ссылки приведены в проекте стандарта N3000. Я еще не загрузил последний черновик:)

GCC prog.cpp: В функции 'int main(): prog.cpp: 27: error: 'base is недоступная база 'производных

Comeau Online "ComeauTest.c", строка 26: Ошибка: преобразование в недоступную базу класс "база" не           позволил       ptr = новый полученный;

Ошибка VS2010 C2243: 'тип cast': преобразование из "производного" в базовое * 'существует, но недоступен

Ответ 2

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

Ответ 3

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

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

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

Как следствие, "внешность" не знает об этом отношении. Это обеспечивается компилятором с помощью этого сообщения inaccessible.

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

Ответ 4

Вы знаете, что class derived наследует от class base, но функция main() не знает этого. Причина, по которой функция main() не знает, что вы сделали class derived наследовать PRIVATELY от class base.

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

Ответ 5

Попробуйте следующее:

#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;
}

Ответ 6

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

Ответ 7

это дает ошибку C2243: 'type cast': преобразование из 'производного *' в 'base *' существует, но недоступно Этот производный класс был унаследован в частном порядке. Поскольку объект базового класса не создается, когда происходит высвечивание, происходит создание. для создания объекта вывода первые вызовы идут для создания объекта базового класса, который не происходит. soltuion - вывести класс публично. не имеет значения, используете ли вы виртуальное ключевое слово с функциями-членами или нет.