我正在学习语言的过程,这是一个否定的怀疑。
是否可以使用虚拟朋友功能?我不知道是否可能,我甚至没有测试它,但它在某些情况下可能有用。例如,对于重载运算符<<()。
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;(<)。
答案 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)
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;
}