多重继承机制与模板相比构建灵活的设计 [英] Mechanics of multiple inheritance compared to templates wrt building flexible designs

查看:200
本文介绍了多重继承机制与模板相比构建灵活的设计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是的较窄版本问题由于过于宽泛而搁置。



现代C ++设计的第6-7页,Andrei Alexandrescu列出了三种方式来实现多重继承比构建灵活设计的模板弱。特别地,他指出由多重继承提供的力学很差(方括号中的文本和格式化是我的上下文):


在这样的设置[ie ],[建立一个灵活的 SmartPtr ,]用户将构建一个多线程,引用计数的智能指针类继承一些 BaseSmartPtr 类和两个类: MultiThreaded RefCounted 。任何有经验的类设计师都知道
这样一个天真的设计不工作。



...


  1. 力学。没有样板代码以受控的
    方式组合继承的组件。结合BaseSmartPtr,MultiThreaded和RefCounted
    的唯一工具是一种称为多重继承的语言机制。语言在组合基类时应用
    简单的叠加,并且建立一组简单的规则
    来访问它们的成员。这是不可接受的,除了最简单的情况。最多
    的时间,您需要协调继承类的工作,仔细到
    获得所需的行为。


当使用多重继承时,可以通过编写调用几个基类的成员函数的成员函数来实现一些非常灵活的编排。那么,从多重继承中缺少并出现在模板中的协调是什么?



请注意,并非多重继承模板相比的每个缺点都可以作为答案,在上述报价中,Andei称为力学的缺点。特别是,请确保您不是在谈论Andrei列出的多重继承的其他两个弱点之一:



  1. 输入信息。基类没有足够的类型信息来执行它们的任务
    。例如,假设您尝试通过从DeepCopy基类派生来为您的智能
    指针类实现深层复制。但是DeepCopy
    有什么接口?它必须创建一个尚不知道的类型的对象。


  2. 状态处理。使用基类实现的各种行为方面必须操纵
    相同的状态。这意味着他们必须使用虚拟继承来继承一个保存状态的
    基类。这使得设计变得复杂,并且使其更加刚性,因为
    的前提是用户类继承库类,反之亦然。



< blockquote>

解决方案

我认为Alexandrescu在力学段落中提到的是在本章的其余部分中阐述的。他指的是比基于继承的类设计更灵活的基于策略的类设计,特别是关于可以实现和组合策略的各种方式 - 这与允许通过多重继承的单个实现和组合相比。



例如,当讨论 Creator 策略时,他指出策略只需要一个Create返回指向正在创建的类的指针,但不指定它是虚拟的或非静态的。他展示了可以创建每个策略的几种方式:一个简单的策略类,如(从1.5节跳过MallocCreator和PrototypeCreator策略)


  template< class T> 
struct OpNewCreator
{
static T * Create()
{
return new T;
}
};

...




 > //库代码
> template< class CreateationPolicy>
> class WidgetManager:public CreationPolicy
> {
> ...
> };




...


$ b b

  //应用程序代码
typedef WidgetManager< OpNewCreator< Widget> > MyWidgetMgr;


或者可以使用模板模板参数实现1)as


  //库代码
template< template< class&类创建策略>
class WidgetManager:public CreationPolicy< Widget>
{
...
}

//应用程序代码
typedef WidgetManager< OpNewCreator> MyWidgetMgr


或(第1.5.2节)成员函数:


  struct OpNewCreator 
{
template< class T> ;
static T * Create()
{
return new T;
}


}



这些是在基于模板的策略类解决方案中可用的灵活机制的示例,在多继承解决方案中不可用。这些特殊的例子可能不是那么令人兴奋,可能是因为他们必须简短和简单的教育原因。


This is a narrower version of the question put on hold due to being too broad.

On pages 6-7 of Modern C++ Design, Andrei Alexandrescu lists three ways in which the multiple inheritance is weaker than templates with respect to building flexible designs. In particular, he states that the mechanics provided by multiple inheritance is poor (the text in square brackets and formatting are mine as per my understanding of the context):

In such a setting [i.e. multiple inheritance], [to build a flexible SmartPtr,] the user would build a multithreaded, reference-counted smart pointer class by inheriting some BaseSmartPtr class and two classes: MultiThreaded and RefCounted. Any experienced class designer knows that such a naïve design does not work.

...

  1. Mechanics. There is no boilerplate code to assemble the inherited components in a controlled manner. The only tool that combines BaseSmartPtr, MultiThreaded, and RefCounted is a language mechanism called multiple inheritance. The language applies simple superposition in combining the base classes and establishes a set of simple rules for accessing their members. This is unacceptable except for the simplest cases. Most of the time, you need to orchestrate the workings of the inherited classes carefully to obtain the desired behavior.

When using multiple inheritance, one can achieve some pretty flexible orchestration by writing member functions that call member functions of several base classes. So, what is the orchestration that is missing from multiple inheritance and present in templates?

Please note that not every disadvantage of multiple inheritance compared to templates goes as an answer here, but only a disadvantage in what Andei calls mechanics in the above quote. In particular, please make sure that you are not talking about one of the other two weaknesses of multiple inheritance listed by Andrei:

  1. Type information. The base classes do not have enough type information to carry on their tasks. For example, imagine you try to implement deep copy for your smart pointer class by deriving from a DeepCopy base class. But what interface would DeepCopy have? It must create objects of a type it doesn’t know yet.

  2. State manipulation. Various behavioral aspects implemented with base classes must manipulate the same state. This means that they must use virtual inheritance to inherit a base class that holds the state. This complicates the design and makes it more rigid because the premise was that user classes inherit library classes, not vice versa.

解决方案

I think that what Alexandrescu is referring to in the "Mechanics" paragraph is expounded upon in the rest of the chapter. He's referring to how much more flexible policy-based class design is than inheritance-based class design, particularly with respect to the various ways in which policies can be implemented and combined - this in comparison to the single implementation and combination allowed through multiple inheritance.

For instance, when discussing the Creator policy he points out that the policy requires only a Create() method that returns a pointer to the class being created, but doesn't specify that it be virtual or non-static. And he shows several ways in which each policy could be created: a straightforward policy class such as (from section 1.5, skipping the MallocCreator and PrototypeCreator policies)

template<class T>
struct OpNewCreator
{
  static T* Create()
  {
    return new T;
  }
}; 

...

>     //Library code
>     template <class CreationPolicy>
>     class WidgetManager:public CreationPolicy
>     {
>     ...
>     };

...

// Application Code
typedef WidgetManager<OpNewCreator<Widget> > MyWidgetMgr;

or it could be implemented with template template parameters (section 1.5.1) as

//Library Code
template <template <class> class Creation Policy>
class WidgetManager : public CreationPolicy <Widget>
{
...
}

// Application Code
typedef WidgetManager<OpNewCreator> MyWidgetMgr

or (section 1.5.2) - implemented as a template member function:

struct OpNewCreator
{
  template <class T>
  static T* Create()
  {
    return new T;
  }

}

These are examples of the flexible mechanics that are available in a template-based policy class solution and not available in a multiple inheritance solution. These particular examples are not maybe all that exciting, probably because they have to be short and simple for pedagogical reasons.

这篇关于多重继承机制与模板相比构建灵活的设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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