【问题标题】:using-declaration for friend function友元函数的使用声明
【发布时间】:2016-11-29 18:07:40
【问题描述】:

在 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.f() 是可能的,因为B 的定义中的using A::f

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

【问题讨论】:

  • 您希望一般情况下可以将B 向上转换为A?那为什么要使用私有继承呢?或者你只是想让operator== 工作?那为什么不直接声明另一个operator==
  • 需要注意的是友元函数不是类的成员,所以不应该使用“upcast”这个词。

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


【解决方案1】:

不,只有 B 可以在内部将自己转换为 A,否则这是不可能的,因为从客户的角度来看,B 不是 an 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] 了解更多信息

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多