Наследование от защищенных классов в C+++

Предположим, у меня есть следующее объявление:

class Over1
{
   protected:
      class Under1
      {
      };
};

Я знаю, что могу сделать следующее:

class Over2 : public Over1
{
   protected:
        class Under2 : public Under1
        {
        };
};

Но есть ли способ объявить Under2 без Over2?

Поскольку вам нужно будет расширить Over1, чтобы использовать любую производную от Under1, это может показаться глупым, но в этой ситуации может быть 30 различных вариантов Under. Я могу либо:

  • Поместите их все в Over1: Not привлекательно, поскольку Over2 может использовать только 1 или 2 из них
  • Поместите их каждый в их собственная версия Over: Not привлекательно с тех пор у вас будет приумножить унаследовать почти от тот же класс.
  • Найдите способ творить дети младше 1 года, не создавая дети старше 1 года

Так возможно ли это?

Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
452
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

Ответ принят как подходящий

Используя шаблоны и явные специализации, вы можете сделать это с помощью всего лишь одного дополнительного объявления класса в Over1.

class Over1
{
protected:
  class Under1
  {
  };

  template <typename T>
  class UnderImplementor;
};

struct Under2Tag;
struct Under3Tag;
struct Under4Tag;

template <>
class Over1::UnderImplementor<Under2Tag> : public Over1::Under1
{
};

template <>
class Over1::UnderImplementor<Under3Tag> : public Over1::Under1
{
};

template <>
class Over1::UnderImplementor<Under4Tag> : public Over1::Under1
{
};

Надеюсь это поможет.

Если вы хотите сохранить защиту Under1, то по определению вам необходимо унаследовать от Over1, чтобы получить к нему доступ. Я бы предложил сделать Under1 общедоступным или использовать пространства имен, как предложил Дуглас.

У меня нет компилятора, чтобы протестировать их прямо сейчас, поэтому я совсем не уверен, что это сработает, но вы можете попробовать это:

class Over1
{
   protected:
      class Under1
      {
      };

   public:
      class Under1Interface : public Under1 
      {
      };
};

class Under2 : public Over1::Under1Interface
{
};

Или, может быть, что-то вроде этого:

class Over1
{
   protected:
      class Under1
      {
      };
};

class Under2 : private Over1, public Over1::Under1
{
};

Или даже:

class Under2;

class Over1
{
   friend class Under2;

   protected:
      class Under1
      {
      };
};

class Under2 : public Over1::Under1
{
};

Хотя это подвергло бы всех рядовых Over1s Under2 - вряд ли то, что вам нужно.

Для меня это звучит немного странно. Почему бы не попробовать по-другому структурировать код. Я думаю, что это может быть хорошим кандидатом для шаблона декоратора, где вы могли бы обернуть свой базовый класс различными декораторами для достижения желаемой функциональности, различные варианты 'under' могли бы быть декораторами. Просто мысль, которую сложно сказать, не зная больше о намерениях вашего кода.

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