首页 > 解决方案 > c++ 的朋友关键字是否意味着更多的访问私有?

问题描述

我编写了简单的类并定义了一个复制构造函数。然后添加朋友相等比较运算符并intInt

template <class T>
class Int {
public:
    T value;
    Int(const T& value_) : value(value_) {
        ;
    }

    friend bool operator==(const Int<T>& f, const Int<T>& s) {
        return f.value == s.value;
    }
};

int main() {
    int a;
    Int<int> x(a);
    x == a;
}

编译成功。

如果我把它friend bool operator==(const Int<T>& f, const Int<T>& s);变成一个非朋友模板。我得到一个编译器错误:

error: no match for 'operator==' (operand types are 'int' and 'Int<int>'
template <class T>
class Int {
public:
    T value;
    Int(const T& value_) : value(value_) {
        ;
    }
};

template <class T>
bool operator==(const Int<T>& f, const Int<T>& s) {
    return f.value == s.value;
}

int main() {
    int a;
    Int<int> x(a);
    x == a;
}

这是否意味着友元函数允许特定的转换?

5 == x也可以。

标签: c++friend-function

解决方案


c++ 的朋友关键字是否意味着更多的访问私有?

根据上下文,它可能会产生更多影响,是的。例如,一个friend内联定义的函数,没有其他声明,只能通过参数相关查找找到,即使它是封闭命名空间的成员:

namespace foo {
    struct bar {
        friend void baz(bar const&) {}
    };
}

int main() {
    foo::bar bar;
    // foo::baz(bar); // ill-formed, no member baz in foo
    baz(bar); // Okay, it *can* be found by ADL
};

这与您的问题没有直接关系,但这operator==就是查找朋友的方式。而且那个朋友本身也不是模板。当您实例化 时Int<int>,这会将一个自由operator==函数(同样不是模板)“注入”到名称空间Int的成员中。当(通过 ADL)查找该运算符函数时x == a,编译器会很高兴地考虑隐式转换aInt<int>,因为我们可以进行隐式转换以匹配常规的自由函数。

说到转换……

我编写了简单的类并定义了一个复制构造函数。

你没有。这是一个带有参数的用户定义构造int const&函数,而不是Int<int> const&像复制构造函数那样。您定义了一个转换构造函数(因为它不是显式的),这正是编译器可以转换aInt<int>上面的方式。

如果我转...

在您的第二个版本中,运算符是一个模板。它仍然由 ADL 查找。但是模板参数推导只考虑参数的确切类型。即, to 的两个参数都operator==必须能够直接绑定到Int<T> const&for some T。Anint不能直接绑定到Int<int> const&,它需要转换。所以它与模板需要进行模板参数推导的参数类型不匹配。因此模板不能被实例化,并且不是候选模板。

这是否意味着友元函数允许特定的转换?

不,这不是友谊。这是模板与非模板业务。您可以定义operator==没有友谊,但它必须是每个实例化的Int

template <class T>
class Int {
public:
    T value;
    Int(const T& value_) : value(value_) {
        ;
    }
};

bool operator==(const Int<int>& f, const Int<int>& s) {
    return f.value == s.value;
}

这也会让你main的身材很好。但正如您所注意到的,单独声明它们并不是很有用,因此许多代码库将使用该friend版本自动“注入”这个免费功能。


推荐阅读