Как разделить определение и объявление с помощью функции друга и наследования

#c #inheritance #struct #declaration #friend

Вопрос:

Мне нужно скомпилировать что-то вроде этого:

 struct Base {  virtual void func1()=0;  // ...  friend void Derived::func2(Base *base); private:  int some_private; }  struct Derived : Base {  virtual func3()=0;  // ...  void func2(Base *child) {  std::cout lt;lt; child-gt;some_private;  } };  

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

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

1. Подумайте о том , чтобы объединить все struct Derived вместе или заменить private на protected .

2.@Фрэнк — создание some_private protected не позволило child-gt;some_private бы войти func2 . Объекты производных типов имеют доступ к своим собственным унаследованным защищенным элементам, но не к защищенным элементам других объектов.

3. У тебя проблема с курицей и яйцом. Вы не можете добавлять функции-члены в friend объявление; компилятор должен был видеть определение Derived , Derived::func2 чтобы быть действительным. Это отличается от функций, не являющихся членами, где a friend declaration также служит объявлением этой функции. Так что лучше всего объявить Derived себя другом.

4. @PeteBecker Спасибо за информацию, я ожидал, что это будет соответствовать private доступу к членам других инстансов.

5. @Фрэнк — да, это естественное ожидание. protected это другое, и я не помню, почему это так, но для этого есть веская причина.

Ответ №1:

У вас есть несколько основных решений. Наиболее очевидным является переход от частного к защищенному. В C защищенный означает, что подклассы имеют доступ.

Вместо этого вы можете добавить более общедоступные (возможно, защищенные) методы доступа.

Вы можете перенаправить ссылку на весь производный класс и подружиться со всем классом.

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

Для этого конкретного решения я бы изменил доступ на защищенный.

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

1. Спасибо, я сделаю весь класс другом, потому что мне не разрешено делать функцию защищенной.

2. protected не сработает. Объекты производных типов имеют доступ к своим собственным унаследованным защищенным элементам, но не к защищенным элементам других объектов. child-gt;some_private пытается использовать защищенный элемент другого объекта, поэтому это запрещено.

3. @PeteBecker child относится к типу Base -суперкласс. То есть вы хотите сказать, что подкласс не может получить доступ к защищенным членам суперкласса?

4. @JosephLarson — нет, я не это сказал. Объект производного типа не может получить доступ к защищенным элементам другого объекта.

5. Не путайте базовый класс с базовым объектом .