0

如何在没有与“无效使用不完整类型”相关的麻烦的情况下实现以下内容?

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
    }
};

更新:错误日志:

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

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

4

3 回答 3

0

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

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);
}
于 2013-05-05T19:49:00.163 回答
0

for 的构造函数Exception是受保护的,这意味着只有派生自的类才Exception允许使用它。该类A不是从 派生的Exception,这就是您在第 99 行收到错误的原因。

编辑:好的,所以我采用了上面的代码,清理它以使其编译,我得到完全相同的错误消息 - 有利于复制!

我可以很好的解决方案是从构造函数中删除“受保护”并使其公开。我找不到任何其他实际可行的解决方案,而且我不确定为什么它在编写时不起作用。

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
    }
};
于 2013-05-05T19:25:31.690 回答
0

就像我能得到的最接近的“学术”例子一样。注意:不推荐。

#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);
}
于 2013-05-05T21:23:06.277 回答