【问题标题】:C++ global extern "C" friend can't reach private member on namespaced classC++ 全局外部“C”朋友无法访问命名空间类的私有成员
【发布时间】:2011-10-12 20:56:27
【问题描述】:

请考虑代码:

#include    <iostream>

using namespace std;

extern  "C"
void    foo( void );

namespace   A
{
    template< int No >
    class   Bar
    {
    private:
        friend  void    ::foo( void );

        static void private_func( int n );
    };

    template< int No >
    void    Bar< No >::private_func( int n )
    {
        cout << "A:Bar< " << No << ">::private_func( " << n << " )" << endl;
    }
}

extern  "C"
void    foo( void )
{
    A::Bar< 0 >::private_func( 1 );
}

int main( )
{
    cout << " ---- " << endl;
    foo( );
}

G++ 给出:

> g++ -Wall -o extern_c extern_c.cpp
extern_c.cpp: In function ‘void foo()’:
extern_c.cpp:20:7: error: ‘static void A::Bar<No>::private_func(int) [with int No = 0]’ is private
extern_c.cpp:29:31: error: within this context

如果我评论namspace A,它将正确编译和运行。

我错过了什么?

我查看了相关主题,但找不到适合我的问题的主题。

谢谢大家。


编辑:

我现在确信extern "C" 与问题无关。 请忽略它。

【问题讨论】:

    标签: c++ templates namespaces extern


    【解决方案1】:

    您需要将朋友声明为 extern "C"。您当前的朋友声明在具有 C++ 名称修饰的全局命名空间中找到了朋友 foo。

    【讨论】:

    • 噢。如果我将第 14 行更改为 friend extern "C" void ::foo( void );,我会收到额外的错误 extern_c.cpp:14:22: error: expected unqualified-id before string constant
    【解决方案2】:

    这是一个 g++ 错误。在 4.4 中存在,在 4.6 中修复。

    UPD:似乎是由templatenamespace 的组合触发的。 extern "C" 不相关,因为它可能被注释掉并且错误仍然存​​在。

    【讨论】:

    • g++ (SUSE Linux) 4.5.1 20101208 [gcc-4_5-branch revision 167585]。我会搜索一个 4.6 并告诉你它是否有效。
    • @Mark B:C++ 标准似乎没有表明如果您是包含在命名空间中的类模板,则应该默默地忽略您的朋友声明。我得出的结论是,执行此操作的编译器一定是错误的。我无法证明这一点,除非可能引用整个标准。
    【解决方案3】:

    我不知道解释,但是如果你把 foo( ) 放到一个命名空间中,它就可以工作。

    #include    <iostream>
    
    using namespace std;
    
    namespace C
    {
        extern  "C"
        void    foo( void );
    }
    
    namespace   A
    {
        template< int No >
        class   Bar
        {
        private:
            friend  void    C::foo( void );
    
            static void private_func( int n );
        };
    
        template< int No >
        void    Bar< No >::private_func( int n )
        {
            cout << "A::Bar< " << No << ">::private_func( " << n << " )" << endl;
        }
    }
    
    
    namespace C
    {
        extern  "C"
        void    foo( void )
        {
            A::Bar< 0 >::private_func( 1 );
        }
    }
    
    int main( )
    {
        cout << " ---- " << endl;
        C::foo( );
    }
    

    结果:

    bbcaponi@bbcaponi friends]$ g++ -Wall namespace_friend.cpp -o namespace_friend
    [bbcaponi@bbcaponi friends]$ ./namespace_friend
     ----
    A::Bar< 0>::private_func( 1 )
    

    【讨论】:

    • 将我真正的foo() 放在命名空间上并不容易,因为它是一个中断服务例程,但我还是会尝试一下。谢谢。
    • 我认为这家伙也有同样的问题,但都没有得到回答:stackoverflow.com/questions/2236712/…
    • 好像是同样的问题,但是空命名空间建议不起作用。我看到了同样的错误。
    • 恭喜!我努力将我的汇编启动迁移到 C++,所以我可以将我的 ISR 名称放在命名空间中,但是......它成功了!!!谢谢男孩,我欠你一杯啤酒。
    猜你喜欢
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 2021-08-16
    • 2012-05-07
    • 1970-01-01
    • 2021-12-30
    • 2015-08-03
    相关资源
    最近更新 更多