无法结合GP和OOP概念

时间:2012-08-11 12:30:30

标签: c++ oop generics

我有一个带有模板化成员函数的类:

class Person
{
  template <typename TItem>
  void DoSomething(TItem item)
  {
    item.Action();
  } 
};

这允许我传递具有Action成员函数的任何项目,该人员将使用该项目执行该操作。所以我能做到:

Person person;
BaseballBat bat;
person.DoSomething(bat);

这种结构允许我用任何类型的对象调用函数。但是,如果我想存储任何类型的对象,我必须模板化该类:

template <TItem>
class Person
{
public:
  void DoSomething()
  {
    this->Item.Action();
  }

  void SetItem(TItem item)
  {
    this->Item = item;
  }
private:
  TItem Item;
};

Person<BaseballBat> person;
BaseballBat bat;
person.SetItem(&bat);
person.DoSomething();

这很烦人,因为我必须重新实例化Person类来改变对象的类型。

或者,我可以从父类派生项目:

class Person
{
public:
  void DoSomething()
  {
    this->Item.Action();
  }

  void SetItem(TItem* item)
  {
    this->Item = item;
  }

private:
  ParentItem* Item;
};

class ParentItem{};

class BaseballBat : public ParentItem
{}

Person person;
BaseballBat bat;
person.SetItem(&bat);
person.DoSomething();

这很烦人,因为我必须维护所有项目的继承结构(看起来非常“非GP”)。

当我有多层“包含对象的对象”时,问题才真正到来 - 也就是说,我必须将函数模板参数从一个非常“顶级”调用“传递”到包含的类:

class BaseballBat
{
  void DoAction();
};

class Child
{
  template <typename TItem>
  void DoAction(TItem item)
  {
    item.DoAction();
  }
};

class Person
{
  Child child;

  // This is annoying to have to pass the item to the person, who then has to pass it to the child. I'd rather "give" the child an Item, then just be able to call child.DoAction(), where the Person doesn't know anything about the item.
  template <typename TItem>
  void PlayWithChild(TItem item)
  {
    child.DoAction(item);
  }
}

有人可以评论如何正确混合功能模板的这两个概念并将对象存储为成员数据吗? (以上只是试图证明的俗气的例子 - 如果它们没有意义,或者你有更好的例子,我全都耳朵:))。

---------编辑--------- 也许更好的例子是简化我的实际情况。 我有一个具有成员函数的类Matcher:

template<typename TDistanceFunctor, typename TPropagationFunctor>
void Matcher::Compute(TDistanceFunctor distanceFunctor, TPropagationFunctor propagationFunctor);

然后我有另一个使用Matcher的类ImageAlgorithm:

template<typename TMatcher>
void ImageAlgorithm::Compute(TMatcher matcher)
{
  matcher.Compute(...); // How do I get the DistanceFunctor and the PropagationFunctor here?
}

我想称之为:

Matcher myMatcher;
.... Setup matcher (how?) ...
ImageAlgorithm algorithm;
algorithm.Compute(myMatcher);

我不知道如何通过ImageAlgorithm对象“传递”DistanceFunctor和PropagationFunctor,因此它可以到达ImageAlgorithm :: Compute调用内的Matcher对象。当然我可以在TDistanceFunctor上模拟Matcher并将一个TDistanceFunctor存储为成员变量,但后来我无法将匹配器使用的距离函数更改为不同类型的距离函子。

1 个答案:

答案 0 :(得分:1)

您可以尝试使用boost::any来保留您的类型变体成员。

概述:

  

boost :: any class(...)支持复制任何值类型,并严格按照其类型安全检查该值的提取。

修改

你是对的,用boost来调用存储的仿函数会有问题。所以我建议另一种方案: 使用std :: function(或boost :: function)来包装你的仿函数。这样,匹配器可以保存相关语法的函数对象(例如,没有参数),并且不需要在仿函数类型上进行模板化。

函数对象已经为你完成了OO(至少在某种意义上)和GP之间的组合。