Я устал как дерьмо, едва могу держать глаза открытыми, так что, возможно, есть более элегантный способ сделать это, и я, конечно, не поддерживаю причудливую идею, что у Базы должно быть максимум семь подклассов. *
// create a template class without a body, so all uses of it fail
template < typename D, typename B> class AllowedInheritance;
class Base {};
class Derived; // forward declaration
// but allow Derived, Base by explicit specialization
template<> class AllowedInheritance< Derived, Base> {};
// privately inherit Derived from that explicit specialization
class Derived : public Base, private AllowedInheritance<Derived, Base> {};
// Do the same with class Compiler Error
// it has no explicit specialization, so it causes a compiler error
class CompileError: public Base,
private AllowedInheritance<CompileError, Base> { };
//error: invalid use of incomplete type
//‘struct AllowedInheritance<CompileError, Base>’
int main() {
Base b;
Derived d;
return 0;
}
Комментарий от jon.h:
Как это остановить, например: class Fail: public Base {}; ? \
Это не так. Но тогда и оригинального примера ОП не было.
К ОП: ваша редакция моего ответа в значительной степени является прямым применением «Любопытно повторяющегося шаблона» Коплиена ]
Я тоже это учел, но проблема в том, что между derived1 : pubic base<derived1>
и derived2 : pubic base<derived2>
нет отношения наследования, потому что base<derived1>
и base<derived2>
- это два совершенно не связанных класса.
Если ваша единственная задача - это наследование реализации, это не проблема, но если вы хотите наследовать интерфейс, ваше решение нарушает это.
Я думаю, что есть способ получить и наследование, и более чистый синтаксис; как я уже говорил, я очень устал, когда писал свое решение. Если ничего другого, то сделать RealBase базовым классом Base в вашем примере - это быстрое решение.
Вероятно, есть несколько способов убрать это. Но я хочу подчеркнуть, что я согласен с markh44: несмотря на то, что мое решение более чистое, мы все еще загромождаем код в поддержку правила, которое не имеет большого смысла. То, что это можно сделать, не означает, что так должно быть.
Если базовому классу десять лет и он слишком хрупок, чтобы быть унаследованным, реальный ответ - это исправить.