Предположим, у меня есть следующее объявление:
class Over1
{
protected:
class Under1
{
};
};
Я знаю, что могу сделать следующее:
class Over2 : public Over1
{
protected:
class Under2 : public Under1
{
};
};
Но есть ли способ объявить Under2 без Over2?
Поскольку вам нужно будет расширить Over1, чтобы использовать любую производную от Under1, это может показаться глупым, но в этой ситуации может быть 30 различных вариантов Under. Я могу либо:
Так возможно ли это?
Спасибо.





Лучше, чем создавать вложенные классы, вы можете захотеть встроить эти замыкания в пространство имен. Таким образом, вам не нужен внешний класс, чтобы получить внутренний класс. В Руководство по стилю 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' могли бы быть декораторами. Просто мысль, которую сложно сказать, не зная больше о намерениях вашего кода.