C++ 友元函数和复制构造函数
当友元函数mag()在类内定义时,下面显示的代码不会编译,但如果在类外定义,则可以编译(注释)。我认为这种差异是由用于将参数类型从A更改为B的复制构造函数造成的。有人能解释一下为什么我应该在外部定义friend函数吗 此外,如果类B是模板类(在顶部添加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
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;
}