友元函数和复制构造函数

use*_*302 1 c++ templates copy-constructor friend-function

当友元函数 mag() 在类内部定义时,下面显示的代码不会编译,但如果在类外部定义(已注释),则可以工作。我认为差异是由用于将参数类型从 A 更改为 B 的复制构造函数引起的。有人可以解释为什么我应该在外部定义友元函数吗?

而且,如果B类是模板类(template <class T>在最上面添加),在外面定义友元函数也是不行的。

#include <iostream>
using namespace std;

class A {
};

class B {
public:
    B(const  A& p) {
        std::cout << "Copy/Conversion constructor" << std::endl;
    }
    friend void mag(const B& p) {
        std::cout << "Mag Inside`.\n";
    }
};
//void mag(const B& p) {
//     std::cout << "Mag Outside.\n";
//}
int main() {
    A a;
    mag(a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

qua*_*dev 5

因为该函数mag没有在全局作用域中声明(当您同时将其设为友元时,您确实定义并声明了它,但仍然需要在其自己的作用域中声明)。

您需要声明它:

class B {
public:
    B(const  A& p) {
        std::cout << "Copy constructor" << std::endl;
    }
    friend void mag(const B& p) {
        std::cout << "Mag Inside`.\n";
    }
};

void mag(const B& p);
Run Code Online (Sandbox Code Playgroud)

如果您使用对象调用magB参数依赖查找将查找B的范围并找到定义。

现在 ifB是一个模板,您需要使用mag适当的参数声明每个版本(如果存在多个版本,您需要帮助编译器解决转换期间的歧义):

template<typename T>
class B {
public:
    B(const  A& p) {
        std::cout << "Copy constructor" << std::endl;
    }

    friend void mag(const B<T>& p) {
        std::cout << "Mag Inside`.\n";
    }
};

void mag(const B<int>& p);  // Version for B<int> declared.
Run Code Online (Sandbox Code Playgroud)