C++中的模板友元函数

在C++中,友元函数很强大,友元不属于类方法,但可以访问类属性。友元有很多用途,比如用于重载四则运算符。然而,友元也可以有模板,之前介绍过模板方法,今天就来介绍一下模板友元。

模板友元有三种定义方式,下面一一来看。

No.1 非模板友元

字面意思是未声明为模板的友元,这类友元与普通友元类似,不过针对不同的模板实例,我们可能要定义相应类型的友元实现。

以下例子全部摘自《C++ prime plus (6th)》,很能说明问题。

template <typename T>

class HasFriend {
private:
  /* data */
  T item;
  static int ct;

public:
  HasFriend (const T & i) : item(i) { ct++; }

  virtual ~HasFriend () { ct--; }

  friend void counts();
  friend void reports(HasFriend &);      // template parameter
};

// each specialization has its own static data member
template <typename T>
int HasFriend<T>::ct = 0;

// non template friend to all HasFriend classes
void counts(/* arguments */) {
  /* code */
  std::cout << "int count: " << HasFriend::ct << ": ";
  std::cout << "double count: " << HasFriend::ct << 'n';
}

// non-template friend to the HasFriend class
void reports(HasFriend<int> & hf) {
  /* code */
  std::cout << "HasFriend: " << hf.item << 'n';
}

// non-template friend to the HasFriend class
void reports(HasFriend<double> & hf) {
  /* code */
  std::cout << "HasFriend: " << hf.item << 'n';
}

在友元counts中,因为它不需要参数,因此只定义了一个实现,它会通过访问全局变量等方法获取不同模板实例。而针对report方法,我们有两个实现,针对两个不同模板实例。

No.2 约束模板友元

这类模板友元需要事先在类外定义好它们的原型(与定义模板函数的方式类似),在类内部也需要定义原型(与定义普通友元函数方式类似)。

以下是一个典型例子:

// template prototypes
template <typename T> void counts();
template <typename T> void report(T &);

// template class
template <typename TT>
class HasFriendT {
private:
  /* data */
  TT item;
  static int ct;

public:
  HasFriendT(const TT & i) : item(i) { ct++; }

  friend void counts<TT>();
  friend void report<>(HasFriendT<TT> &);

  virtual ~HasFriendT() { ct--; }
};

template <typename TT>
int HasFriendT<TT>::ct = 0;

// template friend functions definitions
template <typename T>
void counts(/* arguments */) {
  /* code */
  std::cout << "template size: " << sizeof(HasFriendT<T>) << "; ";
  std::cout << "template counts(): " << HasFriendT<T>::ct << 'n';
}

template <typename T>
void report(T & hf) {
  /* code */
  std::cout << hf.item << 'n';
}

比起非模板友元,这类定义显得更为简洁一些。类HasFriendT的友元report原型定义里有符号“<>”,编译器在这里可以进行自动推断,完整定义是“< HasFriendT<TT> >”。上例同样来自《C++ Prime Plus (6th)》。

No.3 非约束模板友元

非约束模板友元的定义与模板成员的定义颇为类似,即模板原型就声明在类里面,这种方法定义模板友元最简单,见下例:

template <typename T>
class ManyFriend {
private:
  /* data */
  T item;

public:
  ManyFriend (const T & i) : item(i) { }
  virtual ~ManyFriend () { }

  template <typename C, typename D> friend void show2(C &, D &);
};

template <typename C, typename D> void show2(C & c, D & d) {
  std::cout << c.item << ", " << d.item << 'n';
}

上例中,模板友元show2的模板原型就定义于模板类ManyFriend中,这种方法最为直观,简单。

参考:《C++ Prime Plus (6th)》第14章。

作者: YanWen

Web 开发者

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google photo

You are commenting using your Google account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s