模板成员函数 [英] Template member functions

查看:70
本文介绍了模板成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我想绕过模板成员函数不能是虚拟的这一事实.这是我的代码:

Hi,

I would like to bypass the fact that template member functions can''t be virtual. Here is my code:

class A
{
   // abstract class
}

template <class T> class B : public class A
{
   void SetValue(const T p_Value&);
   T m_Value;
}

template <class T> void CVariable<T>::SetValue(const T& p_Value) 
{ 
   m_Value = p_Value ;
}



当我需要将模板对象(类型B< int> B< MyClass> ...)存储在列表中时,我有一个抽象类A可以将其概括化.

问题是我想从基类A做一个SetValue(),因为模板成员函数不能是虚拟的,所以这是不可能的.

我发现的唯一解决方案是使用抽象类型,以便SetValue()不再是模板方法:



As I need so store the template objects (of type B<int>, B<MyClass>...) in a list , I have an abstract class A to generalize them.

The problem is that I would like to do a SetValue() from the base class A which isn''t possible as template member functions can''t be virtual.

The only solution I found is to use an abstract type so that SetValue() is no more a template method:

template <class T>
class DataType : public DataTypeInterface
{
} 

class A
{
   // abstract class
   virtual void SetValue(const DataTypeInterface p_Value&) = 0;
}

template <class T> class B : public class A
{
   void SetValue(const DataTypeInterface p_Value&);
   DataType<T> p_Value;
}

template <class T> void CVariable<t>::SetValue(const DataTypeInterface & p_Value) 
{ 
   // Here do a dynamic_cast to check type T
   m_Value = p_Value ;
}


但是,我不想进行动态转换.有什么解决办法吗?
非常感谢.

Carole


However, I don''t want to do dynamic casts. Is there any solution?
Thanks a lot.

Carole

推荐答案

简单地说-不能.您不能在C ++中将虚拟方法和模板合并到一个派生对象中.您需要根据项目的业务需求在两者之间做出选择.

但是从我的接洽中,您需要通过基本类型进行调用,然后需要使用虚拟方法,这使您的选择更加容易;)

您只能使用模板类型的属性来增强派生类,但这远不及 virtual
To put simply - No. You cannot combine virtual methods and templates in C++ within a single derivation. You need to make a choice between the two, based on business requirements of your project.

But from what I pick up, you need to make calls through the base type, which then requires use of virtual methods, which makes your choice easier ;)

You can only enhance your derived classes with template-type properties, but that''s as far as virtual and template can dance with each other in C++ ;)


//问题是我想从基类A
// The problem is that I would like to do a SetValue() from the base class A
class A
{
public:
  virtual bool CanAcceptValue(const COleVariant& cVal) const = 0;
  virtual bool TrySetValue(const COleVariant& cVal) = 0;
};


是的,这将是一个设计问题:):


Yes, it would be a designe problem :) :

void testYourList(CYourVarList& list)
{
  bool bResult(true);
  
  POSITION pos(list.GetHeadPosition());
  while (pos) {
    COleVariant cVal(3);
    A* pcVar(list.GetNext(pos));
    // generalized call, but maybe without result :) :
    bResult = pcVar->TrySetValue(cVal) && bResult; 
  }

  ASSERT(bResult); // not all vars could be set :)
}


换句话说:即使是A::SetValue(..)
的广义"形式 您将需要有关A对象类型的信息以使设置成功.

这就是为什么我只将不明确的功能概括化的原因:


In other words: even in the "generalized" form of A::SetValue(..)
you will need info about the type of an A-object to have the success of the setting.

That''s why I would generalize only the unspecific functions:

class A
{
public:
  virtual void GetValueAsXMLString(CString& cszValue) const = 0;
};


...并使模板函数的参数变得奇怪:)


...and let the template functions be strange by their parameters :)


您必须问自己的第一个问题是...

在系列B<T>的每个类的每个对象上,哪些操作在语义上等效?如果所有B<T>的操作都是通用的,那么您可以将其粘贴在接口中并在每个派生类中实现,如果不是,您甚至不应该尝试. A中定义的任何内容都必须独立于B<T>中定义的任何内容-包括其模板参数.

设置器绝不会在语义上等效,除非您希望能够执行以下操作:
The first question you have to ask yourself is...

Which operations are semantically equivalent on every object of each class of the family B<T>? If an operation is common to all B<T> then you can stick it in an interface and implement it in each derived class, if it''s not you shouldn''t be even trying. Anything defined in A has to be independent of anything defined in B<T> - including its template parameter.

Setters are never semantically equivalent, unless you want to be able to do something like:
void do_something( A *a, int i, float f )
{
    a->SetValue( i );
    a->SetValue( f );
}

据您从您的评论中可以得知,您不希望这样做.但是像A::print( std::ostream & )这样的东西可以在A的它的定义中,而不依赖于B<T>中的任何东西.

现在,如果您想执行类似原始问题"的操作,则可以使用一个非常讨厌的技巧:

which as far as I can tell from your comment you don''t want. However things like A::print( std::ostream & ) can be in A''s its definition doesn''t rely on anything in B<T>.

Now, if you want to do something like your original "problem" you can use a really nasty hack:

class A
{
    public:
        virtual void do_something_with_a_T( void * ) = 0;
};

template< typename T >
class B
{
    public:
        virtual void do_something_with_a_T( void *p )
        {
            T *t = static_cast< P * >( p );
            // do something with *t here...
            t;
        }
};

class P
{
};

class Q
{
};

int main()
{
    P p;
    Q q;

    B<p> b1;
    A *a = &b1;
    a->do_something_with_a_T( &p );

    B<p> b2;
    a = &b2;
    a->do_something_with_a_T( &q );
}

static_castvoid *的压力应该告诉您,这不是类型安全的,永远不会.

使用您提供的解决方案或等效的解决方案,可以提高类型安全性:

the pressence of the static_cast and void * should tell you this isn''t typesafe and never will be.

You can be more typesafe using the solution you came up with or an equivalent:

class C
{
};

template< typename T >
class D : public C
{
    public:
        virtual void do_something_with_a_T( T * )
        {
        }
};

template< typename T >
void do_something_with_a_T( C *c, T *t )
{
    if( D<t> *p = dynamic_cast< D<t> >( c ) )
    {
        p->do_something_with( *t );
    }
}

int main()
{
    P p;
    Q q;

    D<p> d1;
    C *c = &d1;
    do_something_with_a_T( c, &p );

    D<p> d2;
    c = &d2;
    do_something_with_a_T( c, &q );
}

的优点是不需要额外的类,并且即使完全没有意义,也是类型安全的.

因此,TLDR:

-您的初始设计是错误的,因为B<T>::SetValue在语义上并不等同于所有T
-至少有两个讨厌的骇客,您发现其中一个

which has the advantage of not needing an additional class and is typesafe, if completely pointless.

So, TLDR:

- your initial design was wrong as B<T>::SetValue wasn''t semantically equivalent for all T
- there are at least two nasty hacks, one of which you discovered


这篇关于模板成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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