来自另一个命名空间的友元函数
Friend function from another namespace
/** module.h */
#pragma once
class A {
friend void helpers::logValue(const A &);
int _val;
public:
A() {}
};
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val; // <== ERROR: '_val' is not accessible
}
}
如何在另一个命名空间中声明友元函数?
解决此问题的一种可能方法如下所示:
class A;//forward declaration for class A
namespace helpers{
static void logValue(const A &a); //declaration
}
///////////////////////////////////////////
class A {
friend void helpers::logValue(const A &);
int _val;
};
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val; // works now
}
}
上面程序的输出可见here.
要想出解决办法,就要逆向工作。
我们希望它与 _val
class A
的 private
成员一起工作。
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val;
}
}
第 1 步 为了使上面的函数定义起作用,必须有一个编译器可见的 class A
的前面定义,并且 class 定义必须指定 helpers::logValue()
(具有适当的签名,即 return 类型和参数)是 friend
。所以在 helpers::logValue()
上面的定义之前我们必须放置;
class A {
friend void helpers::logValue(const A &);
int _val;
};
步骤 2 为了使步骤 1 中的 friend
声明有效,编译器必须知道 helpers::logValue()
。这需要命名空间 helpers
的声明区域对编译器可见,编译器声明具有相同签名的函数 logValue()
,并且必须在 A
的定义之前。所以,在我们定义 class A
之前,我们必须做一些像;
namespace helpers{
static void logValue(const A &a);
}
第 3 步 如果 class A
的声明不可见,编译器将在 helpers::logValue()
的这个声明中阻塞。我们已经有一个 class 定义(在第 1 步中创建),因此我们不能再创建一个(这会破坏一个定义规则)。但是我们可以在步骤 2 的代码之前添加一个声明。
class A;
将这些步骤放在一起,我们将这些步骤中的代码以相反的顺序放在一起(即首先放置步骤 3 中的代码,然后是步骤 3 中的代码,依此类推)。然后我们得到
// Step 3
class A;
// Below Step 3 comes code from Step 2
namespace helpers{
static void logValue(const A &a); // works since A is declared
}
// Below Step 2 comes code from Step 1
class A {
friend void helpers::logValue(const A &); // works since helpers::logValue() is declared
int _val;
};
// And now we come to the function definition we want to have work
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val;
}
}
/** module.h */
#pragma once
class A {
friend void helpers::logValue(const A &);
int _val;
public:
A() {}
};
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val; // <== ERROR: '_val' is not accessible
}
}
如何在另一个命名空间中声明友元函数?
解决此问题的一种可能方法如下所示:
class A;//forward declaration for class A
namespace helpers{
static void logValue(const A &a); //declaration
}
///////////////////////////////////////////
class A {
friend void helpers::logValue(const A &);
int _val;
};
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val; // works now
}
}
上面程序的输出可见here.
要想出解决办法,就要逆向工作。
我们希望它与 _val
class A
的 private
成员一起工作。
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val;
}
}
第 1 步 为了使上面的函数定义起作用,必须有一个编译器可见的 class A
的前面定义,并且 class 定义必须指定 helpers::logValue()
(具有适当的签名,即 return 类型和参数)是 friend
。所以在 helpers::logValue()
上面的定义之前我们必须放置;
class A {
friend void helpers::logValue(const A &);
int _val;
};
步骤 2 为了使步骤 1 中的 friend
声明有效,编译器必须知道 helpers::logValue()
。这需要命名空间 helpers
的声明区域对编译器可见,编译器声明具有相同签名的函数 logValue()
,并且必须在 A
的定义之前。所以,在我们定义 class A
之前,我们必须做一些像;
namespace helpers{
static void logValue(const A &a);
}
第 3 步 如果 class A
的声明不可见,编译器将在 helpers::logValue()
的这个声明中阻塞。我们已经有一个 class 定义(在第 1 步中创建),因此我们不能再创建一个(这会破坏一个定义规则)。但是我们可以在步骤 2 的代码之前添加一个声明。
class A;
将这些步骤放在一起,我们将这些步骤中的代码以相反的顺序放在一起(即首先放置步骤 3 中的代码,然后是步骤 3 中的代码,依此类推)。然后我们得到
// Step 3
class A;
// Below Step 3 comes code from Step 2
namespace helpers{
static void logValue(const A &a); // works since A is declared
}
// Below Step 2 comes code from Step 1
class A {
friend void helpers::logValue(const A &); // works since helpers::logValue() is declared
int _val;
};
// And now we come to the function definition we want to have work
namespace helpers {
static void logValue(const A &a) {
std::cout << a._val;
}
}