【问题标题】:Friending a typedef-ed class (c++)与 typedef-ed 类交朋友 (c++)
【发布时间】:2021-12-30 22:28:18
【问题描述】:

我正在经历一些危机,我需要为一个类型定义的模板类添加好友,但我遇到了很多错误(太多错误,无法粘贴到这里)。我已经把 MRE here 放在了,所以你们不必设置文件。

为了完整起见,这里是 .h 文件:

//Keyboard.h
#pragma once
namespace wm
{
    namespace io
    {
        class Keyboard
        {
            //friend wm::MessageHandler;
        private:
            Keyboard(const Keyboard&) = delete;
            void operator=(const Keyboard&) = delete; 
            Keyboard() = default;

        public:
            static Keyboard& Instance();
            static void SomeServerFunc();

        public:
            static void SomeClientFunc();
        };
    }
}

//Mouse.h
#pragma once
namespace wm
{
    namespace io
    {
        class Mouse
        {
            //friend wm::MessageHandler;
            //friend class wm::MessageHandler; ??
        private:
            Mouse(const Mouse&) = delete;
            void operator=(const Mouse&) = delete;
            Mouse() = default;

        public:
            static Mouse& Instance();
            static void SomeServerFunc();

        public:
            static void SomeClientFunc();
        };
    }
}

//MessageHandler.h

#pragma once
#include "Keyboard.h"
#include "Mouse.h"
namespace wm
{
    template < class Keyboard, class Mouse >
    class _MessageHandler
    {
    public:
        static _MessageHandler& Instance();
        _MessageHandler(const _MessageHandler&) = delete;
        void operator=(const _MessageHandler&) = delete;

    private:
        _MessageHandler() = default;
        static void SomeMsgHandelingFunc(); //calls SomeServerFunc from window and mouse
    };

    typedef _MessageHandler<io::Keyboard, io::Mouse> MessageHandler;
}

事实上,上面的代码编译并运行良好。但我想将键盘和鼠标类中的SomeServerFunc 函数设为私有,并使MessageHandler 成为KeyboardMouse 的朋友。我尝试了不同的方法,但到目前为止没有任何效果。

我在做friend class wm::MessageHandler;,但我得到了详细的类型引用 typedef 错误。 然后我发现在 c++ 11 之后,你可以做 friend wm::MessageHandler; 这会产生很多错误。我也试过了

friend wm::_MessageHandler&lt;io::Keyboard, io::Mouse&gt;;

friend class wm::_MessageHandler&lt;io::Keyboard, io::Mouse&gt;;

friend wm::_MessageHandler&lt;Keyboard, Mouse&gt;;

friend class wm::_MessageHandler&lt;Keyboard, Mouse&gt;;

运气不好。

非常感谢任何帮助。

【问题讨论】:

  • 这并没有解决问题,但是以下划线开头的名称后跟大写字母 (_MessageHandler) 和包含两个连续下划线的名称保留供实现使用。不要在你的代码中使用它们。
  • @PeteBecker 这次有点太晚了,但我会在以后的项目中记住这一点:)

标签: c++ templates typedef friend


【解决方案1】:

将键盘和鼠标类中的 SomeServerFunc 函数设为私有,并使 MessageHandler 成为键盘和鼠标的朋友。

我在mouse.h和keyboard.h中添加了类声明,让编译器满意。代码如下:

#pragma once

namespace wm
{
    template < class Keyboard, class Mouse >
    class _MessageHandler;
    namespace io
    {
        class Keyboard;
        class Mouse
        {
        friend class _MessageHandler<io::Keyboard, io::Mouse>;
        private:
            Mouse(const Mouse&) = delete;
            void operator=(const Mouse&) = delete;
            Mouse() = default;

        public:
            static Mouse& Instance();
        private:
            static void SomeServerFunc();

        public:
            static void SomeClientFunc();
        };
    }
}

#pragma once

namespace wm
{
    template < class Keyboard, class Mouse >
    class _MessageHandler;
    namespace io
    {
        class Mouse;
        class Keyboard
        {
        friend class _MessageHandler<io::Keyboard, io::Mouse>;
        private:
            Keyboard(const Keyboard&) = delete;
            void operator=(const Keyboard&) = delete; 
            Keyboard() = default;

        public:
            static Keyboard& Instance();
        private:
            static void SomeServerFunc();

        public:
            static void SomeClientFunc();
        };
    }
}

【讨论】:

    【解决方案2】:

    _MessageHandler 不是一个类,而是一个模板。试试看:

    namespace wm
    {
        template<class Keyboard, class Mouse> class MessageHandler;
    
        namespace io
        {
            class Keyboard
            {
                template<class Keyboard, class Mouse> friend class wm::MessageHandler;
                ...
            };
        }
    }
    

    【讨论】:

    • 说“模板”是不允许的,模板下有一条波浪线。
    • 请指正。
    • 谢谢。我认为这应该可以工作,但现在它说命名空间“wm”没有成员“MessageHandler”。我不能在 Keyboard.h 中包含 MessageHandler.h,因为这将是一个循环引用。我认为这就是它找不到 MessageHandler 的原因
    • 然后尝试前向声明(查看更新)。
    猜你喜欢
    • 2010-09-19
    • 2011-08-10
    • 2016-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 1970-01-01
    相关资源
    最近更新 更多