【问题标题】:Protected Nested Struct Cannot Be Used As Return Type in Derived Outer Class?受保护的嵌套结构不能用作派生外部类中的返回类型?
【发布时间】:2026-01-28 11:00:02
【问题描述】:

我有以下课程(简体)

基类 - ExchangeGatewayUDSHandler.h

    class ExchangeGatewayUDSHandler : public Instrument::IInstrumentListener
    {
    public:

        explicit ExchangeGatewayUDSHandler(const EGUDSConfig& config);
        virtual ~ExchangeGatewayUDSHandler();

        void ProcessEnqueue(UDSRequest& udsRequest);

    protected:

        struct UDSValidityInfo
        {
        public:
            UDSValidityInfo() = default;

            void SetValidity(const bool validity) { isValid_ = validity; }
            void SetReason(const char* reason) { reason_ = reason; }
            inline const std::string GetReason() const { return reason_; }
            inline const bool GetValidity() const { return isValid_; }

        private:
            bool isValid_;
            std::string reason_;
        };

        virtual UDSValidityInfo UDSRequestIsValid(const UDSRequest& udsReq) { return {}; }
   };

如您所见,UDSValidityInfo 是一个嵌套结构。它只会在ExchangeGatewayUDSHandler 及其所有派生类中创建。唯一的问题是,由于某种原因,在派生类 ExchangeGatewayICEUDSHandler 的 CPP 文件中,我无法返回 UDSValidityInfo

派生类 - ExchangeGatewayICEUDSHandler.h

    class ICEGatewayUDSHandler: public ExchangeGatewayUDSHandler
    {
    public:

        ICEGatewayUDSHandler(const ExchangeGatewayUDSHandlerConfig& config);

    protected:

        virtual UDSValidityInfo UDSRequestIsValid(const UDSRequest& udsReq) override; // No error

    };

派生类 - ExchangeGatewayICEUDSHandler.cpp

    ICEGatewayUDSHandler::ICEGatewayUDSHandler(const ExchangeGatewayUDSHandlerConfig& config)
        :   ExchangeGatewayUDSHandler(config) {};

    // Error in return type
    UDSValidityInfo ICEGatewayUDSHandler::UDSRequestIsValid(const UDSRequest& udsReq) 
    {
        UDSValidityInfo validityObject{}; // No error creating the struct here.
        validityObject.SetValidity(true);

        if (udsReq.legs_.empty())
        {
            validityObject.SetReason("The UDS contains no legs.");
            validityObject.SetValidity(false);
        }

        return validityObject;
    }

Visual Studio 19 说错误是:

标识符“UDSValidityInfo”无法识别

我还收到函数类型错误 (virtual UDSValidityInfo UDSRequestIsValid(const UDSRequest& udsReq) override;),即使 .h 文件(声明它的位置)中没有此函数的错误,说明这两个函数不兼容。

我不确定为什么会这样。当我将结构设为静态时,问题就消失了,但我认为这是作弊。

谢谢。

【问题讨论】:

    标签: c++ class nested inner-classes


    【解决方案1】:

    ExchangeGatewayUDSHandlerICEGatewayUDSHandler 类声明之外的 .cpp 文件中,您需要在方法返回值中限定 UDSValidityInfo,以便编译器知道在哪里查找该类型,因为它已经还没有看到 ExchangeGatewayUDSHandler::ICEGatewayUDSHandler:: 限定词,例如:

    ExchangeGatewayUDSHandler::UDSValidityInfo ICEGatewayUDSHandler::UDSRequestIsValid(const UDSRequest& udsReq) 
    {
        ...
    }
    

    或者,您可以使用带有尾随返回类型的auto,以便编译器在看到UDSValidityInfo 类型之前看到ExchangeGatewayUDSHandler::ICEGatewayUDSHandler:: 限定符,从而知道要查看的正确范围为它,例如:

    auto ICEGatewayUDSHandler::UDSRequestIsValid(const UDSRequest& udsReq) -> UDSValidityInfo
    {
        ...
    }
    

    【讨论】:

    • 所以我几乎需要在基类 (ExchangeGatewayUDSHandler) 上使用范围解析运算符来指示编译器在该类中查找此结构。奇怪它怎么找不到它。我的意思是,我不需要限定派生类的基类中声明的函数。那么为什么会有差异呢?第二招也很巧妙。非常感谢。
    • 是的,您需要限定方法定义(而不是声明)的返回类型,因为当时编译器正在解析定义,先解析返回类型,还没有解析返回方法所属的类名。所以你必须帮助编译器一点。当您在派生类中声明方法覆盖时,编译器知道 declaration 所在的上下文,因此需要较少的限定。上下文很重要。
    • 该死的……每天都在学习。谢谢雷米。