C++ 在编译时将继承限制为所需的类数
我们有一个限制,一个类不能作为超过7个类的基类。 有没有办法在编译时强制执行上述规则 我知道Andrew Koenig的可用锁定技术可以防止类被继承,但只有当我们尝试实例化该类时,它才会失败。当推导自身时,这难道不能做到吗 基类可以知道谁是它的孩子。所以我想我们可以宣布一个朋友的组合 类并封装它们以强制执行此规则。假设我们试试这样的东西C++ 在编译时将继承限制为所需的类数,c++,inheritance,friend,C++,Inheritance,Friend,我们有一个限制,一个类不能作为超过7个类的基类。 有没有办法在编译时强制执行上述规则 我知道Andrew Koenig的可用锁定技术可以防止类被继承,但只有当我们尝试实例化该类时,它才会失败。当推导自身时,这难道不能做到吗 基类可以知道谁是它的孩子。所以我想我们可以宣布一个朋友的组合 类并封装它们以强制执行此规则。假设我们试试这样的东西 class AA { friend class BB; private: AA() {} ~AA() {} }; clas
class AA {
friend class BB;
private:
AA() {}
~AA() {}
};
class BB : public AA {
};
class CC : public AA
{};
类CC的派生将生成编译器警告abt不可访问dtor。然后我们就可以挂国旗了
使用编译器调整将这些警告标记为错误(比如将所有警告标记为错误),但我不想依赖这些技术
另一种方式,但在我看来相当笨拙的是:-
class B;
class InheritanceRule{
class A {
public:
A() {}
~A() {}
};
friend class B;
};
class B {
public:
class C : public InheritanceRule::A
{};
};
class D : public InheritanceRule::A{};
类D的派生将被标记为编译器错误,这意味着所有要派生的类都应该在类B内部派生。这将至少允许检查从类a派生的类的数量,但不会阻止任何人添加更多
这里有人有办法吗?如果底层阶级不需要知道谁是他们的孩子,那就更好了
注意:充当基类的类本身可以实例化(它不是抽象的)
提前感谢,
编辑1:根据jon.h的评论,稍微修改一下
// create a template class without a body, so all uses of it fail
template < typename D>
class AllowedInheritance;
class Derived; // forward declaration
// but allow Derived by explicit specialization
template<>
class AllowedInheritance< Derived> {};
template<class T>
class Base : private AllowedInheritance<T> {};
// privately inherit Derived from that explicit specialization
class Derived : public Base<Derived> {};
// Do the same with class Fail Error
// it has no explicit specialization, so it causes a compiler error
class Fail : public Base<Fail> {}; // this is error
int main()
{
Derived d;
return 0;
}
//创建一个没有主体的模板类,因此它的所有使用都会失败
模板
类允许继承;
派生类;//远期申报
//但允许通过显式专门化派生
模板
类AllowedInheritation<派生>{};
模板
类基:私有AllowedInheritation{};
//从显式专门化派生的私有继承
派生类:公共基{};
//对类失败错误执行相同的操作
//它没有显式的专门化,因此会导致编译器错误
类失败:公共基{};//这是一个错误
int main()
{
导出d;
返回0;
}
许多不同的静态代码分析工具提供了有关继承层次结构的信息。与其尝试在代码中处理它,我将研究一种工具,它可以为继承层次结构设置一些规则,如果不遵循这些规则,则构建失败。可能需要花费一点美元,您可能需要编写一个自定义规则(我已经看到了继承深度,但没有看到您想要的继承“宽度”)。但是,从长远来看,我认为这是你最好的选择
根据评论:我已经使用了一些成功。有点斯彭迪。有一些可能有更好的选择。我累得像垃圾一样,眼睛几乎睁不开,所以可能有一种更优雅的方法来做到这一点,我当然不赞成一个基最多应该有七个子类的奇怪想法
// 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;
}
//创建一个没有主体的模板类,因此它的所有使用都会失败
模板类允许继承;
类基{};
派生类;//远期申报
//但允许通过显式专门化派生、基本
模板类AllowedInheritation<派生,基>{};
//从显式专门化派生的私有继承
派生类:公共基,私有允许继承{};
//对类编译器错误执行相同操作
//它没有显式的专门化,因此会导致编译器错误
类编译器错误:公共基,
私有允许继承{};
//错误:不完整类型的使用无效
//“结构允许继承”
int main(){
碱基b;
导出d;
返回0;
}
jon.h的评论:
这是如何停止的,例如:类Fail:public Base{}\ 没有。但是OP最初的例子也没有 ] 我也考虑过这一点,但问题是
derived1:pubic base
和derived2:pubic base
之间没有继承关系,因为base
和base
是两个完全不相关的类
若您唯一关心的是实现的继承,那个么这并没有问题,但若您想要接口的继承,那个么您的解决方案就打破了这一点
我认为有一种方法可以同时获得继承和更清晰的语法;正如我提到的,当我写我的解决方案时,我非常累。如果没有其他问题,那么在您的示例中使RealBase成为base的基类是一个快速修复方法
可能有很多方法可以解决这个问题。但我想强调的是,我同意markh44:尽管我的解决方案更简洁,但我们仍然在混乱代码,以支持一个毫无意义的规则。仅仅因为这是可以做到的,并不意味着它应该做到
如果所讨论的基类已存在十年,并且太脆弱,无法从中继承,那么真正的答案是修复它。对不起,我不知道如何使用编译器强制执行任何此类限制 就我个人而言,我不会费心将规则强制写入代码本身——你在代码中乱放与代码所做的事情无关的东西——这不是干净的代码 我宁愿试着放松这条规则,而不是跳圈。相反,它应该是一个指导原则,如果必要的话可以打破,并且与团队中的其他人达成一致 当然,我不知道你到底在做什么,所以这个规则可能是合适的,但总的来说可能不是 任何编程“规则”说你永远不能做x或者你必须永远做y,这几乎都是错误的!注意这里的“几乎”一词 有时您可能需要7个以上的派生类,那么您会怎么做呢?多跳几圈。还有,为什么是7?为什么不是6点或8点?这太武断了——这又是一个糟糕规则的标志
如果您必须这样做,正如JP所说,静态分析可能是更好的方法。与其用断言来混乱代码,您还可以使用类似的语法分析