2010-09-09 1 views
19

Вот мой код -Почему переход между производными * на базу * не выполняется с помощью частного наследования?

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

+0

Вы не объявили метод 'virtual'. Какую ошибку вы получаете точно? – Dirk

+8

В текущей форме это не имеет никакого отношения к функции 'sid()'. Вы используете личное наследование, поэтому преобразование из 'производного *' в 'base *' не выполняется. Это то, о чем вы спрашиваете, или это что-то связано с методом 'sid()'? – Naveen

+1

Возможный дубликат [Защищенный производный класс] (http://stackoverflow.com/questions/433965/protected-derived-class) – kennytm

ответ

16

$ 11,2/4 states-

A base class B of N is accessible at R, if

  • an invented public member of B would be a public member of N, or
  • R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or
  • R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
  • there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R."

Здесь 'B' есть 'база', 'N' является 'Derived' и 'R' является основным.

  1. Рассмотрите вторую пулю: «R встречается у члена или друга класса N, ...». Этот пункт не применяется, так как «R» (основной) не является ни членом, ни другом «N» (Derived)

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

  3. Рассмотрим 4-й очередной раз пулями этот пункт не применяется

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

$ 11.2/5 штатов -

If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11). [ Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. —end note ]

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

EDIT 2:

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

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

GCC prog.cpp: In function ‘int main()’: prog.cpp:27: error: ‘base’ is an inaccessible base of ‘derived’

Comeau Online "ComeauTest.c", line 26: error: conversion to inaccessible base class "base" is not allowed ptr = new derived;

VS2010 error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible

+0

Можете ли вы любезно предоставить свою ссылку. – Bruce

+0

@Bruce: О, извините, я забыл упомянуть, что ссылки взяты из проекта стандарта N3000. Я обнаружил, что C++ 03 имеет некоторые запутанные заявления, чтобы понять это понятие. Соответственно, я обновляю свой пост. – Chubsdad

+0

См. Ответы Дугласа Лидера и ereOn для удобных для пользователя и быстрых решений. – mwjohnson

35

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

+0

Почему я не могу это сделать? Каковы проблемы реализации в этом? – Bruce

+2

Частное наследование означает, что вы не хотите, чтобы интерфейс базового класса был доступен другим кодом, кроме кода дочернего класса. – Klaim

+7

На самом деле не хотелось проводить время, интерпретируя ответ Чубсдада, и это было именно то, что мне нужно было знать. Отсутствует заявление 'public' в определении моего производного класса. – User

0

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

+4

. Вы знаете, я НЕНАВИЖУ его, когда люди сбиты с толку, и не оставляйте комментарий. –

+0

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

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; 
} 
+0

Вы имели в виду 'virtual void sid()'? Также вам нужно, чтобы деструктор базового класса был 'virtual'. – Naveen

+0

@Naveen: Спасибо. Я был на пути, чтобы добавить деструктор;) Также да, 'private' был опечаткой. – ereOn

+0

Виртуальный деструктор - хорошая идея. Помещение виртуальной функции sid противоречит заявленной цели оригинального плаката. –

6

Вы знаете, что class derived наследует от class base, но функция main() не знает об этом. Причина, по которой функция main() не знает, что вы сделали class derived наследуйте ЧАСТНОСТЬ от class base.

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

+0

@WP: Не могли бы вы рассказать о своем ответе – Bruce

+0

Chubsdad did ... –

8

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

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

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

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

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

0

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

Смежные вопросы