【问题标题】:C++ friend class with same name in different namespaces在不同命名空间中具有相同名称的 C++ 友元类
【发布时间】:2013-04-17 17:27:59
【问题描述】:

我在不同的命名空间中有两个同名的类。我无法修改类的名称。 我想向其中一个类添加一个方法,但不允许将其添加为公共方法。另一个类是用 C++/CLI 作为 ref 类编写的,需要访问此方法。 我尝试使用朋友类,但我不知道应该如何使用它。

标准 C++ 中的 dll:

namespace X
{
    class A
    {
        protected:
        __declspec(dllexport) void method();
    }
}

C++/CLI 中的应用程序

namespace Y
{
    ref class A
    {
        void someMethod()
        {
            X::A otherClass;
            otherClass.method();
        }
    }
}

我尝试了以下方法: 朋友类 Y::A; // 编译器错误 C2653: Y 不是类或命名空间名称

当我声明命名空间 Y 时,我收到错误 C2039: 'A' : is not a member of 'Y'

我不能在命名空间 Y 中添加类 A 的前向声明,因为类 A 是使用标准 C++ 编译的,并且在前向声明中我必须将其声明为 ref 类。

编译器:Visual Studio 2008

有人有想法吗?

谢谢

解决方案(感谢 Sorayuki):

#ifdef __cplusplus_cli
    #define CLI_REF_CLASS ref class
#else
    #define CLI_REF_CLASS class
#endif

namespace Y { CLI_REF_CLASS A; }

namespace X
{
    class A
    {
        protected:
        friend CLI_REF_CLASS Y::A;
        __declspec(dllexport) void method();
    }
}

【问题讨论】:

    标签: c++ class namespaces c++-cli friend


    【解决方案1】:

    我不确定这种伎俩是否允许。

    但也许你想看看这种“黑客”:

    在 c++/cli 中

    namespace Y
    {
        class HackA : public X::A {
            public:
            void CallMethod() { method(); }
        };
        ref class A
        {
            void someMethod()
            {
                X::A otherClass;
                assert(sizeof(HackA) == (X::A));
                HackA* p = (HackA*) &otherClass;
                p->CallMethod();
            }
        };
    };
    

    编辑:

    我测试过这个可以通过编译

    namespace Y { ref class A; };
    
    namespace X
    {
        class A
        {
            friend ref class Y::A;
            protected:
            __declspec(dllexport) void method();
        };
    };
    
    namespace Y
    {
        ref class A
        {
            void someMethod()
            {
                X::A otherClass;
                otherClass.method();
            }
        };
    };
    

    也许您只需要复制 X::A 的头文件并通过在命名空间 X 之前添加声明(未定义)Y::A 来编辑副本。并包含“副本”。

    【讨论】:

    • 我认为这行得通,但这不是一段很好的代码。如果没有其他方法,我必须使用这种 hack,但我不知道我是否可以使用它。
    • 谢谢,但这不能用标准的 C++ 编译器编译。该 dll 不使用 .NET。我已经和我的客户谈过了:我可以使用您的第一个答案。
    • 我知道。所以我建议你复制那个 .h 然后修改它,否则那个 dll 将无法编译。顺便说一句,你可以定义一个宏 MYREF 什么的,当用其他编译器编译时它被定义为空,当用 .net 编译时它被定义为“ref”。
    • 我已经添加了解决方案。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 1970-01-01
    • 2017-05-03
    • 2014-01-12
    • 2011-12-01
    • 1970-01-01
    • 2012-02-27
    相关资源
    最近更新 更多