在编译时将继承限制为所需数量的类 [英] Restrict inheritance to desired number of classes at compile-time

查看:108
本文介绍了在编译时将继承限制为所需数量的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We have a restriction that a class cannot act as a base-class for more than 7 classes. Is there a way to enforce the above rule at compile-time?

我知道Andrew Koenig的Usable_Lock技术来防止类被继承,但它只有当我们试图实例化类时才会失败。这是不是可以在派生自身时做呢?

I am aware of Andrew Koenig's Usable_Lock technique to prevent a class from being inherited but it would fail only when we try to instantiate the class. Can this not be done when deriving itself?

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

The base-class is allowed to know who are its children. So i guess we can declare a combination of friend classes and encapsulate them to enforce this rule. Suppose we try something like this

class AA {
   friend class BB;
   private:
      AA() {}
      ~AA() {}
};

class BB : public AA {

};

class CC : public AA 
{};

类CC的派生将生成编译器警告abt unrecessible dtor。然后,我们可以使用编译器调整(例如将所有警告标记为错误)将
标记为错误警告,但我不想依赖此类技术。

The derivation of class CC would generate a compiler warning abt inaccessible dtor. We can then flag such warnings as errors using compiler tweaks (like flag all warnings as errors), but i would not like to rely on such techniques.

另一种方式,但对我看起来相当笨拙是: -

Another way, but to me looks rather clumsy is:-

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的派生将被标记为编译器错误,意味着所有要导出的类

The derivation of class D will be flagged as a compiler error, meaning all the classes to be derived should be derived inside class B. This will allow atleast an inspection of the number of classes derived from class A but would not prevent anyone from adding more.

任何人在这里有一个方式做吗?更好的是,如果基类不需要知道是谁的孩子。

Anyone here who has a way of doing it ? Better still if the base-class need not know who are its children.

注意:充当基类的类本身可以实例化(它不是抽象的)

NOTE: The class which acts as a base-class can itself be instantiated (it is not abstract).

提前感谢,

EDIT-1:根据jon.h的注释,修改

EDIT-1: As per Comment from jon.h, a slight modification

// 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;
}


推荐答案

,几乎不能让我的眼睛睁开,所以可能有一个更优雅的方式来做到这一点,我肯定不支持一个奇怪的想法,一个基地应该最多有七个子类。

I'm tired as crap, can barely keep my eyes open, so there's probably a more elegant way to do this, and I'm certainly not endorsing the bizarre idea that a Base should have at most seven subclasses.

// 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的注释:

Comment from jon.h:


如何停止实例:class Fail:public Base {}; ? \

How does this stop for instance: class Fail : public Base { }; ? \

没有。但是OP的原始示例也没有。

It doesn't. But then neither did the OP's original example.

到OP:你对我的回答的修订几乎是对Coplien的Curiously recurring template pattern的直接应用]

d认为也是这样,但是在 derived1:pubic base< derived1> 和a derived2:pubic base之间没有继承关系的问题。由于 base< derived1> base< derived2> 是两个完全不相关的类。

I'd considered that as well, but the problem with that there's no inheritance relationship between a derived1 : pubic base<derived1> and a derived2 : pubic base<derived2>, because base<derived1> and base<derived2> are two completely unrelated classes.

如果你唯一关心的是继承的实现,这没有问题,但如果你想继承接口,你的解决方案打破了这一点。

If your only concern is inheritance of implementation, this is no problem, but if you want inheritance of interface, your solution breaks that.

我想有一种方法来获得继承和更清晰的语法;正如我所说的,当我写我的解决方案时,我很累。如果没有别的,通过使RealBase的基类Base在你的例子是一个快速修复。

I think there is a way to get both inheritance and a cleaner syntax; as I mentioned I was pretty tired when I wrote my solution. If nothing else, by making RealBase a base class of Base in your example is a quick fix.

可能有很多方法来清理。但我想强调,我同意markh44:即使我的解决方案更干净,我们仍然杂乱的代码支持一个规则,没有什么意义。

There are probably a number of ways to clean this up. But I want to emphasize that I agree with markh44: even though my solution is cleaner, we're still cluttering the code in support of a rule that makes little sense. Just because this can be done, doesn't mean it should be.

如果有问题的基类是十岁,太脆弱,不能继承,那么真正的答案是解决它。

If the base class in question is ten years old and too fragile to be inherited from, the real answer is to fix it.

这篇关于在编译时将继承限制为所需数量的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆