Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 友元函数和复制构造函数_C++_Templates_Copy Constructor_Friend Function - Fatal编程技术网

C++ 友元函数和复制构造函数

C++ 友元函数和复制构造函数,c++,templates,copy-constructor,friend-function,C++,Templates,Copy Constructor,Friend Function,当友元函数mag()在类内定义时,下面显示的代码不会编译,但如果在类外定义,则可以编译(注释)。我认为这种差异是由用于将参数类型从A更改为B的复制构造函数造成的。有人能解释一下为什么我应该在外部定义friend函数吗 此外,如果类B是模板类(在顶部添加template),则在外部定义友元函数也将不起作用 #include <iostream> using namespace std; class A { }; class B { public: B(const A&am

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

此外,如果类B是模板类(在顶部添加
template
),则在外部定义友元函数也将不起作用

#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;
}
#包括
使用名称空间std;
甲级{
};
B类{
公众:
B(施工A&p){

std::cout,因为函数
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);

因为函数
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);

mag
不在全局范围内声明。此外,在函数重载解析情况下也会起作用,但它严格基于参数的类型,而不是类型。如果要使用ADL,请使用
B
调用
mag

int main() {
    A a;
    mag(B(a));
    return 0;
}

mag
不在全局范围内声明。此外,在函数重载解析情况下也会起作用,但它严格基于参数的类型,而不是类型。如果要使用ADL,请使用
B
调用
mag

int main() {
    A a;
    mag(B(a));
    return 0;
}

如果某个类是模板,则不能为该类定义这样的友元函数,因为:

例如,假设您有
B
B
,编译器将B视为
B
还是
B

因此,您必须将mag声明为模板,如下所示:

// Inside the class :
friend void mag(const B<T>& p);

// Outside the class :
template <typename T> void mag(const B<T>& p) {
     std::cout << "Mag Outside.\n";
}
//类内部:
friend void mag(const B&p);
//课外活动:
模板无效磁图(施工图B&p){

std::cout如果某个类是模板,则不能为该类定义这样的友元函数,因为:

例如,假设您有
B
B
,编译器将B视为
B
还是
B

因此,您必须将mag声明为模板,如下所示:

// Inside the class :
friend void mag(const B<T>& p);

// Outside the class :
template <typename T> void mag(const B<T>& p) {
     std::cout << "Mag Outside.\n";
}
//类内部:
friend void mag(const B&p);
//课外活动:
模板无效磁图(施工图B&p){
std::cout1。
若类B不是模板类,则必须在类外定义mag函数,因为它是友元函数,这意味着它是非类成员函数

class B{
    public:
        B(const A& p){
            cout<<"copy constructor"<<endl;
        }    
        friend void mag(const B& p);
    private:
        int k;
};

void mag(const B& p){
    cout<<"mag"<<endl;
}
B类{
公众:
B(施工A&p){
cout1。
若类B不是模板类,则必须在类外定义mag函数,因为它是友元函数,这意味着它是非类成员函数

class B{
    public:
        B(const A& p){
            cout<<"copy constructor"<<endl;
        }    
        friend void mag(const B& p);
    private:
        int k;
};

void mag(const B& p){
    cout<<"mag"<<endl;
}
B类{
公众:
B(施工A&p){

Cuth< P>章节中的C++草案标准N33 37,与此问题相关:

11.3好友

4首先在友元声明中声明的函数具有外部链接(3.5)。否则,该函数将保留其先前的链接(7.1.1)

6当且仅当类是非本地类(9.8)、函数名不合格且函数具有命名空间作用域时,才能在类的友元声明中定义函数。[示例:

-[结束示例]

7此类函数是隐式
内联的
。在类中定义的友元函数在其定义的类的(词法)范围内。在类之外定义的友元函数不在(3.4.1)范围内


在您的例子中, MAG在类<代码> b/COD>的词法范围内定义,即名称“代码> MAG<代码>,即使在外部有链接之外也不可见。为了使函数在类<代码> b>代码>之外可见,必须在代码< b>代码>之外声明。

C++标准草案N333的部分。7与此问题相关的:

int main() {
    A a;
    mag(B(a));
    return 0;
}
11.3好友

4首先在友元声明中声明的函数具有外部链接(3.5)。否则,该函数将保留其先前的链接(7.1.1)

6当且仅当类是非本地类(9.8)、函数名不合格且函数具有命名空间作用域时,才能在类的友元声明中定义函数。[示例:

-[结束示例]

7此类函数是隐式
内联的
。在类中定义的友元函数在其定义的类的(词法)范围内。在类之外定义的友元函数不在(3.4.1)范围内


在您的示例中,
mag
是在类
B
的词法范围中定义的,即名称
mag
在类外不可见,即使它具有外部链接。要使函数在类
B
之外可见,必须在
B
之外声明它(常量A&)
是转换构造函数而不是副本构造函数。您也没有指定编译时出现的错误。错误为“错误:使用未声明的标识符“mag”。
B(常量a&)
是转换构造函数而不是副本构造函数。您也没有指定编译时出现的错误。错误是“错误:使用未声明的标识符“mag”。好的,可以,但仅仅将成员函数定义为“友元”是否足以为其提供全局作用域?如果不涉及副本构造函数,f.i将传递一个B对象直接使用mag,不需要在外部声明mag…不,这是不够的。第二种情况之所以有效,是因为其他情况下仍然缺少全局范围声明。好的,谢谢。如果类B是模板类,在外部定义函数似乎不起作用。我想有一种版本
int main() {
    A a;
    mag(B(a));
    return 0;
}