【问题标题】:Is there a way to access the private parts of a different instantiation of the same class template?有没有办法访问同一类模板的不同实例化的私有部分?
【发布时间】:2010-11-14 14:02:02
【问题描述】:

在我对模板的持续探索中,我不仅在它所拥有的 ItemType 上对我的 Container 类进行了模板化,而且还在确定它应该如何对项目排序的 Functor 参数上进行了模板化。到目前为止,一切顺利。

当我想将一个 Container 的内容复制到另一个时,我遇到了一个小问题:如果两个 Container 具有不同的 Functor 类型,那么它们在技术上是不相关的类。因此,不允许容器 A 访问容器 B 的非公开内容。除了将我需要访问的所有内容设为公开之外,有没有什么好的方法来处理这个问题?也许是某种模板“朋友”声明的方法?

演示问题的示例代码如下:

#include <stdio.h>

class FunctorA {};
class FunctorB {};

template <class ItemType, class Functor> class MyContainer
{
public:
   MyContainer() : _metaData(0) {/* empty */}

   template<class RHSFunctor> void CopyFrom(const MyContainer<ItemType, RHSFunctor> & copyFrom)
   {
      _metaData = copyFrom._metaData;
      _item     = copyFrom._item;
   }

private:
  int _metaData;
  ItemType _item;
};

int main(int argc, char ** argv)
{
   MyContainer<void *, FunctorA> containerA;
   MyContainer<void *, FunctorB> containerB;

   containerA.CopyFrom(containerB);  // error, containerA::CopyFrom() can't access containerB's private data!
   return 0;
}

【问题讨论】:

  • 澄清标题以反映您无法实例化类但可以实例化类模板。混淆的部分原因在于类模板本身不是类型,但每个实例化都是不同的类型。

标签: c++ templates private public


【解决方案1】:

您可以创建一个仅在 ItemType 上模板化的基本模板类,将数据保留在那里,拥有完整的 2-args 模板子类作为基础,并将复制源放在基类中,因为它不依赖于反正函子。即:

template <class ItemType> class MyContainerBase
{
public:
   MyContainerBase() : _metaData(0) {/* empty */}

   void CopyFrom(const MyContainerBase<ItemType> & copyFrom)
   {
      _metaData = copyFrom._metaData;
      _item     = copyFrom._item;
   }

protected:
  int _metaData;
  ItemType _item;
};

template <class ItemType, class Functor> class MyContainer:
    public MyContainerBase<ItemType>
{
  // whatever you need here -- I made the data above protected
  // just on the assumption you may need to access it here;-)
};

【讨论】:

  • Jeremy,这种技术,将大量行为放在具有较少模板参数(有时没有)的基类中,然后在子类中添加特定的额外功能是一种非常通用的技术,并且被大量使用. (GNU libstdc++ 有很多值得一看的案例。)
  • 太棒了,这正是我想要的。谢谢!
【解决方案2】:

正如您所指出的,您还可以使用朋友功能:

class FunctorA {};
class FunctorB {};

template <class ItemType, class Functor> class MyContainer
{
public:
  MyContainer() : _metaData(0) {/* empty */}

  template<class CmnItemType, class LHSFunctor, class RHSFunctor>
  friend void Copy(const MyContainer<CmnItemType, LHSFunctor> & copyFrom
    , MyContainer<CmnItemType, RHSFunctor> & copyTo);

private:
  int _metaData;
  ItemType _item;
};

template<class CmnItemType, class LHSFunctor, class RHSFunctor>
void Copy(const MyContainer<CmnItemType, LHSFunctor> & copyFrom
  , MyContainer<CmnItemType, RHSFunctor> & copyTo)
{
  copyTo._metaData = copyFrom._metaData;
  copyTo._item     = copyFrom._item;
}


int main(int argc, char ** argv)
{
  MyContainer<void *, FunctorA> containerA;
  MyContainer<void *, FunctorB> containerB;

  Copy(containerB, containerA);
  return 0;
}

【讨论】:

    猜你喜欢
    • 2021-10-29
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    相关资源
    最近更新 更多