基类的虚拟朋友函数?

时间:2012-08-27 13:25:31

标签: c++ class function virtual friend

我正在学习语言的过程,这是一个否定的怀疑。

是否可以使用虚拟朋友功能?我不知道是否可能,我甚至没有测试它,但它在某些情况下可能有用。例如,对于重载运算符<<()。

DerivedClass dc;
BaseClass &rbc = dc;
cout << rbc;

我的猜测是可能的,但我不确定,因为朋友的功能没有在类设计中实现,理论上也不是它的一部分(尽管在这个例子中,从概念上讲,运算符&lt;&lt;(&lt; )应该是一种方法,但由于语法限制,不可能将其实现为一种方法。

编辑:我关心的是这个例子:

BaseClass bc;
DerivedClass dc;
BaseClass *pArr[2];
pArr[1] = bc;
pArr[2] = dc;
for (int i = 0; i < 2; i++)
    cout << pArr[i];

在这个混合对象数组中,我想要为每个对象调用正确的运算符&lt;&lt;(<)。

5 个答案:

答案 0 :(得分:34)

不,friend virtual函数完全没有意义。

friend函数是这样的,它们不是方法(也就是成员函数),并且有权访问private的{​​{1}} / protected成员。

class函数只能是成员函数。您不能拥有virtual非会员功能。


您可以使virtual引用基类,然后调用某个operator<<成员函数。这样,您可以使virtual“几乎虚拟”:)


例如

operator<<

将打印class A { public: virtual void f() const { std::cout << "base"; } }; class B: public A { public: virtual void f() const { std::cout << "derived"; } }; std::ostream& operator<<(std::ostream& os, const A& a ) { a.f(); return os; } int main() { B b; std::cout << b << std::endl; return 0; }

答案 1 :(得分:9)

Virtual Friend Function Idiom

  C ++中的

友元函数不能声明为虚拟,因此不能动态绑定友元函数。如果层次结构中的每个类都需要重载的友元函数,则将友元函数应用于整个类的层次会变得很麻烦。缺乏对动态绑定的支持使得很难证明它实际上是类接口的扩展。虚拟朋友的功能习惯优雅地解决了这个问题。

您需要使用虚拟朋友功能惯用法。它在gist中所说的是在Base中保留一个虚函数,让friend函数调用该函数。它将多态调用Derived Class的函数

直接从链接

复制示例
class Base {
  public:
    friend ostream& operator << (ostream& o, const Base& b);
  protected:
    virtual void print(ostream& o) const{ ... }
};
/* make sure to put this function into the header file */
inline std::ostream& operator<< (std::ostream& o, const Base& b){
  b.print(o); // delegate the work to a polymorphic member function.
  return o;
}

class Derived : public Base {
  protected:
    virtual void print(ostream& o) const{ ... }
};

答案 2 :(得分:6)

您可以在没有朋友功能的情况下解决此问题,仅使用公共虚拟方法:

struct BaseClass {
  virtual void print(std::ostream& os) const;
};

struct DerivedClass {
  virtual void print(std::ostream& os) const;
};

std::ostream& operator<<(std::ostream& os, const BaseClass& obj) {
  obj.print(os);
  return os;
}

如果公开print方法没有意义,那么ostream& operator<<可以声明为friend

答案 3 :(得分:1)

虚拟函数不是朋友函数。 虚函数仅在程序中使用继承时使用,其中一个类作为基类,其他类作为派生类。 虚函数用于动态绑定对象。这意味着您可以将派生类的对象存储在基类的指针中,并仍然调用该特定派生类的方法。这个概念称为Polymorphism

友元函数用于访问类的私有接口。即使您的班级没有使用继承,也可以使用它们。

答案 4 :(得分:1)

您不能同时是朋友和同一类的虚拟功能。但是,朋友操作员可以从正在打印的对象中调用虚函数。

ostream& operator<<(ostream& stream, const BaseClass& rbc)
{
    rbc.print_on(stream);
    return stream;
}