首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >是否可以将友元函数声明为静态函数?

是否可以将友元函数声明为静态函数?
EN

Stack Overflow用户
提问于 2013-11-08 03:58:58
回答 1查看 26.1K关注 0票数 38

下面是一些编译良好并运行良好的C++示例代码:

代码语言:javascript
复制
class A
{
public:
   A() {/* empty */}

private:
   friend void IncrementValue(A &);
   int value;
};

void IncrementValue(A & a)
{
   a.value++;
}   

int main(int, char **)
{
   A a;
   IncrementValue(a);
   return 0;
}

然而,我想要做的是将IncrementValue()声明为静态的,这样它就不会被其他编译单元看到或调用:

代码语言:javascript
复制
static void IncrementValue(A & a)
{
    a.value++;
}

然而,这样做会给我一个编译错误:

代码语言:javascript
复制
temp.cpp: In function ‘void IncrementValue(A&)’:
temp.cpp:12: error: ‘void IncrementValue(A&)’ was declared ‘extern’ and later ‘static’
temp.cpp:8: error: previous declaration of ‘void IncrementValue(A&)’

..。并且将友元声明更改为match也没有帮助:

代码语言:javascript
复制
friend static void IncrementValue(A &);

..。因为它给出了这个错误:

代码语言:javascript
复制
temp.cpp:8: error: storage class specifiers invalid in friend function declarations

我的问题是,在C++中有没有办法让一个(非方法)朋友函数声明为静态的?

EN

回答 1

Stack Overflow用户

发布于 2016-12-03 00:49:22

虽然Praetorian的answer在技术上是正确的,因为它回答了您明确提出的问题,但我认为这不是一个有用的答案,因为他提出的建议既不合理,也不能满足您所声明的希望定义只能在friend类的翻译单元中调用的方法的目标。

他的解决方案有两个问题。首先,由于引用翻译模块中没有定义静态声明的友元函数这一错误,任何其它翻译单元都将无法编译,该翻译单元的头部包含以静态函数声明为首的类定义。其次,引用翻译单元可以通过定义静态声明的函数本身来消除编译错误,并且该定义将能够访问该函数被声明为朋友的类的所有私有数据。这表明朋友函数应该始终保留它们的默认公共链接,因为这可以防止由于公共链接函数的多个定义成为编译错误而导致的潜在封装漏洞。

我相信@engf在他对你的问题的评论中是正确的,你需要一个在同一个翻译单元中定义的朋友类,作为你希望它能够访问的类。例如。

代码语言:javascript
复制
// A.h

class A
{
public:
   A() : _value(0) {}
private:
   int _value;
   friend struct A_Accessor;
};
代码语言:javascript
复制
// A.cpp

struct A_Accessor
{
   static void IncrementValue(A& a)
   {
      ++a._value;
   }
};


TEST(StaticInit, IncrementA)
{
   A a;
   A_Accessor::IncrementValue(a);
}

这将以一种方式定义IncrementValue,允许它访问A的私有数据,但不能从A的转换模块外部引用。

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19845478

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档