在处理异常时无效地使用不完整类型

invalid use of incomplete type in handling exceptions

本文关键字:用不完 类型 无效 处理 异常      更新时间:2023-10-16

如何实现以下功能,而不会出现"无效使用不完整类型"的问题?

class A { // line#10
    /*(...) some fields and methods here. */
    // more fields of the following functionality exist, storing data about object A's state.
    int SomeField;
    class Exception {
        /*(...) some fields and methods here. */
        public: enum ProblemCase { /*(...) */ };
        protected: Exception( ProblemCase issue, int additionalData ) { /*(...)*/ } // line#29
        friend Exception A::BuildException( ProblemCase ); // line#34
    };
    inline Exception BuildException( Exception::ProblemCase issue ) {
        return Exception( issue, SomeField ); // line#99
    }
};

update: error log:

A.hpp:34:72: error: invalid use of incomplete type ‘class A’
A.hpp:10:7: error: forward declaration of ‘class A’
A.hpp: In member function ‘A::Exception A::BuildException(A::Exception::ProblemCase)’:
A.hpp:29:20: error: ‘A::Exception::Exception(A::Exception::ProblemCase, int)’ is protected
A.hpp:99:46: error: within this context

请注意,名称已更改,因此错误日志中的字符数不正确。

仅仅重新排列声明是不可能的。需要对进行一些重大的重组。

class A {
  public:
    class Exception;
  private:
    class AHelper
    {
      public:
        friend class A;
        class ExceptionBase
        {
          public:
            typedef enum {Something} ProblemCase;
        };
      private:
        inline static Exception BuildException(ExceptionBase::ProblemCase issue, int something);
    };
    int SomeField;
  public:    
    class Exception : public AHelper::ExceptionBase
    {
      public:
        using AHelper::ExceptionBase::ProblemCase;
      protected:
        Exception(ProblemCase issue, int additionalData) {}
        friend Exception AHelper::BuildException(ProblemCase, int);
    };
    inline Exception BuildException(Exception::ProblemCase issue);
};
inline A::Exception A::AHelper::BuildException(A::Exception::ProblemCase issue, int something)
{
    return A::Exception(issue, something);
}
inline A::Exception A::BuildException(A::Exception::ProblemCase issue)
{
    return AHelper::BuildException(issue, SomeField);
}

Exception的构造函数是受保护的,这意味着只有从Exception派生的类才允许使用它。类A不是从Exception派生的,这就是为什么您在第99行得到错误。

编辑:好吧,所以我拿了上面的代码,清理它使它编译,我得到完全相同的错误信息-很好的复制!

我可以确定的解决方案是从构造函数中删除"protected"并使其为公共的。我找不到任何其他的解决方案,实际上工作,我不知道为什么它不工作,因为它是写的。

class A {
    int SomeField;
    class Exception 
    {
    public: 
       enum ProblemCase { PB1, PB2 };
    public: 
       Exception( ProblemCase issue, int additionalData ) {  } 
    };
    inline Exception BuildException( Exception::ProblemCase issue ) {
        return Exception( issue, SomeField ); // line#99
    }
};

只是一个"学术"的例子,我可以得到最接近的。注意:不推荐。

#include <type_traits>
struct A { // line#10
    /*(...) some fields and methods here. */
    // more fields of the following functionality exist, storing data about object A's state.
    int SomeField;
    class Exception;
    template < typename T >
    inline Exception BuildException( T issue );
    class Exception {
        /*(...) some fields and methods here. */
        public: enum ProblemCase { FIRST /*(...) */ };
        protected: Exception( ProblemCase issue, int additionalData ) { /*(...)*/ } // line#29
        // accepted by clang, not by g++??
        // friend Exception A::BuildException<ProblemCase>( ProblemCase ); // line#34
        // accepted by both
        template < typename T >
        friend Exception A::BuildException( T ); // line#34
    };
};
// there's no need to define it outside the class
// (I originally used an explicit specialization)
template < typename T >
A::Exception A::BuildException( T issue ) {
    // optional
    static_assert(std::is_same<typename std::remove_const<T>::type, Exception::ProblemCase>::value, "Wrong type!");
    return Exception( issue, SomeField ); // line#99
}
int main()
{
    A a;
    a.BuildException(A::Exception::FIRST);
}