从具体类派生抽象模板类

Posted

技术标签:

【中文标题】从具体类派生抽象模板类【英文标题】:Deriving an abstract template class from concrete class 【发布时间】:2012-09-25 04:03:48 【问题描述】:

假设我有以下课程:

template <typename T>
class CModule
public:
  virtual void process( std::multiamp<int, T>)  = 0;
 

和派生类:

template <typename T>
class CModuleDeriv: public CModule<T>
public:
  virtual void process( std::multiamp<int, T>)....;

 

以及我不想实现此功能的类:

class Client

std::vector<CModule<T>*> oModuleList_; // <--- this is not possible error

public:
  void moduleLoader()
    oModuleList_.resize(1);
    if( some_condition )
      oModuleList_[0] = CModuleDeriv<int>();
    else
      oModuleList_[0] = CModuleDeriv<double>();
    
  

有可能吗? 还有其他解决方案吗? 我不能使用提升:/

【问题讨论】:

请检查我的答案的编辑 【参考方案1】:

首先,请在以后发布几乎可以编译的代码(或者更好的可以编译的代码!),因为您忽略的那些“小”细节有时会改变代码的语义。因此,提交几乎可编译的代码具有几乎明确的语义......

以下代码可能会或可能不会解决您的问题:

#include<map>
#include<vector>

template <class, class>
class TypedMultimap;

class TypeErasedMultimap 
public:
    template <class T1, class T2>
    std::multimap<T1,T2> & getMap() 
        return  static_cast<TypedMultimap<T1,T2> &> (*this); // This is not type safe, it can be made to be, but boost people already did it so I won't bother
    

    virtual ~TypeErasedMultimap()
;

template <class T1, class T2>
class TypedMultimap: public TypeErasedMultimap, public std::multimap<T1,T2> ;

class CModule

    virtual void process( TypeErasedMultimap &)  = 0;

;

template <typename T>
class CModuleDeriv: public CModule

    // At his point, please ask yourself, how will you make sure that the right kind
    // of map arrives at this call? I can't answer this, since this is related to
    // the semantics...
    virtual void process( TypeErasedMultimap & map_)
        std::multimap<int,T> &map = map_.getMap<int,T>();
        //...
    ;

;

class Client

// Why are you using raw pointers?!?
std::vector<CModule*> oModuleList_; 

public:
  void moduleLoader()
    oModuleList_.resize(1);
    if( 1/*some condition*/ )
      oModuleList_[0] = new CModuleDeriv<int>();
    else
      oModuleList_[0] = new CModuleDeriv<double>(); // the types are lost forever...
    
  

// ~Client() you MAY OR MAY NOT!!! need a destructor since your vector is holding pointers: use smart pointers!!!
;

int main() 

这本身并不能解决您的问题,因为您的未编译代码片段即使已编译也无法解决任何问题。您将具有固有不同类型的事物推送到一个通用列表并丢失它们的类型,那么您将如何知道将来如何使用这些元素?这是一个语义问题。

我会大胆猜测这可能就是你想要做的:

#include<boost/variant.hpp>
#include<boost/shared_ptr.hpp>
#include<boost/make_shared.hpp>
#include<map>
#include<vector>

typedef boost::variant<std::multimap<int,int>, std::multimap<int,double> /* possibly some others */ > VariantMap;

class CModule
public:
    virtual void process( VariantMap &)  = 0;

;

class CModuleDeriv1: public CModule, public boost::static_visitor<> 
public:
    virtual void process( VariantMap & in)
    boost::apply_visitor(*this, in);    
    ;

    template < class T>
    void operator()(std::multimap<int,T> & in) 
    // do your type safe processing here
    
;

class CModuleDeriv2: public CModule, public boost::static_visitor<>
public:
    virtual void process( VariantMap & in)
    boost::apply_visitor(*this, in);
    ;

    template < class T>
    void operator()(std::multimap<int,T> & in) 
    // do other kind of processing here
    
;


class Client

// Why are you using raw pointers?!?
std::vector<boost::shared_ptr<CModule> > oModuleList_; 

public:
  void moduleLoader()
    oModuleList_.resize(1);
    if( 1/*some condition*/ )
      oModuleList_[0] = boost::make_shared<CModuleDeriv1>();
    else
      oModuleList_[0] = boost::make_shared<CModuleDeriv1>(); // the types are safe now, even though not known
    
  

// ~Client() you MAY OR MAY NOT!!! need a destructor since your vector is holding pointers: use smart pointers!!!
;

int main() 

看,没有更多的评论唠叨:)

【讨论】:

以上是关于从具体类派生抽象模板类的主要内容,如果未能解决你的问题,请参考以下文章

从一个模板类转换为另一个(都派生自同一个基类)

c++ 模板化抽象基类数组,不违反严格别名规则

覆盖派生模板类的返回类型

模板类与抽象类

如何使用 C++ 中的模板编程从基类创建派生类?

如果从抽象类派生,则无法使用具体类指针调用函数