Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在编译时将继承限制为所需的类数_C++_Inheritance_Friend - Fatal编程技术网

C++ 在编译时将继承限制为所需的类数

C++ 在编译时将继承限制为所需的类数,c++,inheritance,friend,C++,Inheritance,Friend,我们有一个限制,一个类不能作为超过7个类的基类。 有没有办法在编译时强制执行上述规则 我知道Andrew Koenig的可用锁定技术可以防止类被继承,但只有当我们尝试实例化该类时,它才会失败。当推导自身时,这难道不能做到吗 基类可以知道谁是它的孩子。所以我想我们可以宣布一个朋友的组合 类并封装它们以强制执行此规则。假设我们试试这样的东西 class AA { friend class BB; private: AA() {} ~AA() {} }; clas

我们有一个限制,一个类不能作为超过7个类的基类。 有没有办法在编译时强制执行上述规则

我知道Andrew Koenig的可用锁定技术可以防止类被继承,但只有当我们尝试实例化该类时,它才会失败。当推导自身时,这难道不能做到吗

基类可以知道谁是它的孩子。所以我想我们可以宣布一个朋友的组合 类并封装它们以强制执行此规则。假设我们试试这样的东西

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所说,静态分析可能是更好的方法。

与其用断言来混乱代码,您还可以使用类似的语法分析