【问题标题】:Can't Implement Method in Subnamespace For Derived Class无法在子命名空间中为派生类实现方法
【发布时间】:2021-11-09 04:18:25
【问题描述】:

具有嵌入式 C 经验的 Dotnet 开发人员在这里进入 cpp 领域,让您了解我的经验/知识。

我在src/Core/Window/ 中有一个基类Window

namespace Pyrite::Core::Window
{
    class PYR_API Window
    {
    public:
        using EventCallbackFn = std::function<void(Pyrite::Event&)>;

        virtual ~Window();
        virtual void OnUpdate();

        virtual uint32_t GetWidth() const = 0;
        virtual uint32_t GetHeight() const = 0;

        virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
        virtual void SetVSync(bool isEnabled) = 0;
        virtual bool IsVSyncEnabled() const = 0;

        static Window* Create(const WindowProperties& props = WindowProperties());
    };
}

由此,我为特定于平台的WindowsWindow 创建了一个派生类,我想将其存储在src/Core/Window/Platform/ 中:

namespace Pyrite::Core::Window::Platform
{
    class WindowsWindow : public Pyrite::Core::Window::Window
    {
    public:
        WindowsWindow(const WindowProperties& properties);
        virtual ~WindowsWindow();

        void OnUpdate() override;

        inline uint32_t GetWidth() const override { return m_Data.Width;    }
        inline uint32_t GetHeight() const override { return m_Data.Height; }

        inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; }
        void SetVSync(bool isEnabled) override { m_Data.VSyncEnabled = isEnabled; }
        bool IsVSyncEnabled() override {return m_Data.VSyncEnabled; }
    private:

        virtual void Init(const WindowProperties& properties);
        virtual void Close();

        GLFWwindow* m_Window;

        struct WindowData
        {
            std::string Title;
            uint32_t Width, Height;
            bool VSyncEnabled;

            EventCallbackFn EventCallback;
        };

        WindowData m_Data;

    };
}

但是,在 WindowsWindow.cpp 中,当我尝试为 Window::Create() 创建实现时,我收到一个错误,提示无法在此处定义它:

namespace Pyrite::Core::Window::Platform
{
    static bool s_GLFWInitialised = false;
        
    Window* Window::Create(const WindowProperties& properties)
    {
        return new WindowsWindow(properties);
    }
}
'Pyrite::Core::Window::Window *Pyrite::Core::Window::Window::Create(const Pyrite::Core::Window::WindowProperties &)': symbol cannot be defined within namespace 'Platform'  PyriteEngine    C:\repos\Pyrite\PyriteEngine\src\Core\Window\Platform\WIndowsWindow.cpp 9   

当我调整命名空间使它们都位于Pyrite::Core::Window 中时,它似乎消失了……但是,我无法在子命名空间中定义它似乎很奇怪。如果可能的话,我希望我的命名空间遵循我的文件夹结构(因为这几乎是我所习惯的,它使事情保持逻辑和整洁)并将平台特定的东西隐藏在子命名空间中似乎对我有意义。

这只是我完全不能做的事情还是我在这里遗漏了什么?

【问题讨论】:

  • 我会很感激为什么这有一个密切的投票......据我所知,这是一个结构良好的问题,有一个明确的问题,我尝试过的步骤以及我我希望实现
  • 最后一票是我的。我试图用给定的代码进行重现,并且不得不对给定的代码进行过多的更改,同时筛选出不相关的编译器错误。当我放弃、投票关闭并继续前进时,我仍然有 17 个错误。赔率太高了,当我解决非必要问题时,我要么不小心解决了您正在寻求帮助的问题,要么在解决其他问题时不小心删除了导致它的代码。我建议构建一个minimal reproducible example
  • 但是,我再次尝试制作 godbolt.org/z/1eqGKxYaT 的罐头,我相信它忠实地重现了您的问题。
  • 我认为问题在于Pyrite::Core::Window 是正确的封闭命名空间,而不是Pyrite::Core::Window::Platform。但是到目前为止,我已经编写了太多代码,以至于我可能大错特错。如果我是对的,我怀疑你已经知道这一点并在问,“为什么会这样?”是的。我很确定这是你的问题。
  • @user4581301 我有额外的子命名空间来匹配我的文件夹结构...感谢您花时间解释近距离投票,是的,这可能是公平的,我想它可能是这样的对于有经验的人来说很明显,我不需要和 MRE ......但是,在 Discord 上的某人的帮助下,我找到了一个解决方案(我认为),我认为你得出了同样的结论,我只需要将Window::Create 包装在与基类相同的命名空间中,并将其余实现放在平台命名空间中(我认为)

标签: c++ inheritance namespaces


【解决方案1】:

首先,C++ 中源文件和命名空间之间的分离是一个特点,因为它们可以在适当的情况下遵循相同的结构,但其他组织也是可能的。除此之外,不可能按照您的要求去做(字面意思),因为它会产生奇怪的 “兄弟姐妹” 用于名称查找,这被认为比它们的价值更麻烦.特别是,给定

namespace A {
  int i;
  struct X {void f(); void g(); void h();};
  namespace B {
    void g();
    namespace C {
      int i;
      void h();
      void X::f() {g(); h(); ++i;}  // pretend this is OK
    }
  }
}

目前尚不清楚B::g 和/或C::h 是否比X::gX::h 更“接近”X::f 的定义。将X::f 的定义移入或移出找到i 的类更改也不清楚。

您通常可以使用 using-declarations 来解决这些限制:上面的 X 可能在 B 中定义,但随后 暴露A 中(或C!)。有时,受影响的成员函数也可以移动到属于不同命名空间的 base 类中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-14
    • 2021-07-22
    • 2015-05-29
    • 2018-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-27
    相关资源
    最近更新 更多