c++ - 友元函数的使用声明

标签 c++ c++11 c++14 using friend

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

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.f() 之所以可行,是因为 B 的定义中使用了 A::f

是否可以编写一个类似的声明,使友元函数 operator==(A&, A& ),这样b == b2就可以在main()中调用了吗?

最佳答案

不,只有 B 可以在内部将自己转换为 A,否则是不可能的,因为从客户端的角度来看 B 不是 < strong>一个 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 从调用者的角度来看(由于私有(private)继承)。

您需要提供自己的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]

关于c++ - 友元函数的使用声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40872786/

相关文章:

c++ - OpenCV C++多线程提高帧率

C++文件发送程序

c++ - 如何在 Internet 临时文件夹中创建 .txt 文件?

C++ 移动/删除符号

c++ - std::unordered_set::equal_range 迭代器问题

c++ - 删除 QListWidgetItem:QListWidget::takeItem(item) vs 删除项目

C++使用显式参数检测自由函数的存在

c++ - 不为 emplace() 定义构造函数的解决方法

c++ - 从 C++ map<T, const T&> 返回值的检索返回相同的对象

c++ - 如何为一个类提供多个开始/结束代理