友元函数的使用声明

using-declaration for friend function

本文关键字:声明 函数 友元      更新时间:2023-10-16

在 C++11 中,可以使用using声明使私有基类的公共成员可供外部(公共)访问。例如

class A {
private:
int i = 2;
public:
void f() { i = 3; }
friend bool operator==(const A& l, const A& r) { return l.i == r.i; }
};
class B : private A {
public:
using A::f;
};
int main() {
B b, b2;
b.f();
}

由于B定义中的using A::fb.f()是可能的。

是否可以编写一个类似的声明,使 friend 函数operator==(A&, A&)B&向上转换为A&,以便可以在main()中调用b == b2

不,只有B可以在内部将自己转换为A,否则这是不可能的,因为从客户端的角度来看,B不是A而是具有A

即使您将friend bool operator=替换为成员函数equals

class A {
private:
int i = 2;
public:
void f()  { i = 3; }
bool equals(const A& r){return i == r.i;}
};
class B : private A {
public:
using A::f;
using A::equals; 
};

在编译时,您永远无法调用b.equals(b2)因为从调用者的角度来看,不可能从某种B类型到一种A进行隐式转换(由于私有继承)。

您需要提供自己的operator==或将继承更改为publicprotected。下面是一个示例,其中B声明自己的friend bool operator==

class B : private A {
public:
using A::f;
friend bool operator==(const B& l, const B& r)
{
return (static_cast<A>(l) == static_cast<A>(r)) && true; 
// "true" is a stand-in for some other condition
}
};

在isocpp阅读更多内容


编辑: 如果你真的想玩游戏,你会注意到我说过隐转换是不可能的,但一些显式转换是可能的。因为B技术上确实派生自A所以你可以进行指针强制转换来使其工作,但我不建议这样做:

class A {
private:
int i = 2;
public:
void f()  { i = 3; }
bool equals(const A* r){return i == r->i;}
};
class B : private A {
public:
using A::f;
using A::equals;
};
int main() {
B b, b2;
b.f();
(::A*)(&b)->equals((::A*)(&b2));  
}

或者,如果您希望保留原始operator==语法,则可以使用指针强制转换的丑陋表亲引用转换。

class A {
private:
int i = 2;
public:
void f()  { i = 3; }
friend bool operator==(const A& l, const A& r) { return l.i == r.i; }
};
class B : private A {
public:
using A::f;
};
int main() {
B b, b2;
b.f();
((::A&)(b)) == ((::A&)(b2));  
}

参见 §11.2 [class.access.base] 了解更多信息