Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中的属性处理+;设计_C++_Oop_Attributes - Fatal编程技术网

C++ C+中的属性处理+;设计

C++ C+中的属性处理+;设计,c++,oop,attributes,C++,Oop,Attributes,这就是困扰我的地方:我有一个类的层次结构,其中包含一组属性,这些属性要么是强制性的,要么不是强制性的。这些类被序列化为XML(或其他内容)。必须的属性应该一直序列化,否则的属性只有在我指定的情况下才应该序列化 我正在寻找一种尽可能自动化这个过程的方法,而不必特别检查每个属性是否设置了值 以下是一个例子: class Book { QString m_author; // this is optional QString m_secondaryAuth

这就是困扰我的地方:我有一个类的层次结构,其中包含一组属性,这些属性要么是强制性的,要么不是强制性的。这些类被序列化为XML(或其他内容)。必须的属性应该一直序列化,否则的属性只有在我指定的情况下才应该序列化

我正在寻找一种尽可能自动化这个过程的方法,而不必特别检查每个属性是否设置了值

以下是一个例子:

 class Book
 {

     QString m_author;           // this is optional
     QString m_secondaryAuthor;  // this is optional
     QString m_title;            // this is mandatory

 public: 
     QString serializePlainText()
     {
         QString result = "Book:";
         result += m_title;
         if(m_author.length()) result+= " by "+m_author;
         if(m_SecondaryAuthor.length()) result+= " and "+m_SecondaryAuthor;
         return result;
     }

     void setTitle(const QString& title)
     {
         m_title = title;
     }

     void setAuthor(const QString& author)
     {
         m_author = author;
     }
 };
当然,这只是一个简单的例子,现实生活要复杂得多,类可以有数百个属性。问题的第二部分来了:我需要能够以更严格的方式设置属性,即不使用映射,在映射中我将值映射到字符串属性,但或多或少类似于上面的示例(使用setter函数
setTitle(const QString&)
…等…)

考虑到:

  • 无需手动声明和检查所有属性
  • 有一个好看的、程序员友好的API吗
  • 我或多或少被Qt卡住了,但是这不是强制性的

    谢谢, f、 所以。我的第一个想法是“使用一种好的动态语言”,但我想这不是一个选择。不过,我确实有一些模糊的建议

  • 使用映射。映射可以被迭代,从而大大减少序列化代码的痛苦。这也使得添加新属性变得更加容易
  • 使用一个getter和一个setter函数,因为这是客户端代码调用的最简单、最整洁的API
  • 分别保留已知属性名称和元数据值的映射
  • 调用set后,可以在属性元数据表中查找请求的属性名称。然后,您可以执行所需的任何验证或转换。当然,我假设您不需要为每个属性的结构设置一组独特而复杂的要求……大多数属性可能只需要最小值之类的东西还是最大长度


    序列化时,您可以迭代属性元数据表,查找所有必需属性的名称,并在属性值表中查找它们。之后,遍历属性值表,并序列化所有剩余项。

    如果您愿意使用预处理器为您生成代码,您可以使用n.例如,你可以通过以下方式做一些事情:

    #define GET_TYPE( pair ) BOOST_PP_TUPLE_ELEM( 2, 0, pair )
    #define GET_NAME( pair ) BOOST_PP_TUPLE_ELEM( 2, 1, pair )
    
    #define DECLARE_MANDATORY( r, data, elem ) GET_TYPE( elem ) GET_NAME( elem );
    
    #define DECLARE_MANDATORY_ATTRIBUTES( attributes ) \
        BOOST_PP_SEQ_FOR_EACH( DECLARE_MANDATORY, ~, attributes )
    
    #define DECLARE_OPTIONAL( r, data, elem ) boost::optional< GET_TYPE( elem ) > GET_NAME( elem );
    
    #define DECLARE_OPTIONAL_ATTRIBUTES( attributes ) \
        BOOST_PP_SEQ_FOR_EACH( DECLARE_OPTIONAL, ~, attributes )
    
    #define MANDATORY_ACCESSORS( r, data, elem ) \
        BOOST_PP_CAT( void set_, GET_NAME( elem ) ) (GET_TYPE( elem ) const & value) { GET_NAME( elem ) = value; } \
        GET_TYPE( elem ) BOOST_PP_CAT( get_, GET_NAME( elem ) ) () const { return GET_NAME( elem ); }
    
    #define DEFINE_MANDATORY_ACCESSORS( attributes ) \
        BOOST_PP_SEQ_FOR_EACH( MANDATORY_ACCESSORS, ~, attributes )
    
    #define OPTIONAL_ACCESSORS( r, data, elem ) \
        BOOST_PP_CAT( void set_, GET_NAME( elem ) ) (GET_TYPE( elem ) const & value) { GET_NAME( elem ).reset(value); } \
        GET_TYPE( elem ) BOOST_PP_CAT( get_, GET_NAME( elem ) ) () const { return *GET_NAME( elem ); }
    
    #define DEFINE_OPTIONAL_ACCESSORS( attributes ) \
        BOOST_PP_SEQ_FOR_EACH( OPTIONAL_ACCESSORS, ~, attributes )
    
    class Book
    {
        #define BOOK_MANDATORY_ATTRIBUTES ((std::string, title))
        #define BOOK_OPTIONAL_ATTRIBUTES ((std::string, author)) ((std::string, secondaryAuthor))
    
      public:
    
        DECLARE_MANDATORY_ATTRIBUTES( BOOK_MANDATORY_ATTRIBUTES )
        DECLARE_OPTIONAL_ATTRIBUTES( BOOK_OPTIONAL_ATTRIBUTES )
    
        DEFINE_MANDATORY_ACCESSORS( BOOK_MANDATORY_ATTRIBUTES )
        DEFINE_OPTIONAL_ACCESSORS( BOOK_OPTIONAL_ATTRIBUTES )
    };
    
    int main()
    {
        Book b;
        b.set_title("H2G2");
    
        std::cout << b.get_title();
    
        b.set_author("Douglas Adams");
        std::cout << b.get_author();
    }
    

    我不完全理解您试图实现的目标:您想给出一个强制和可选属性的列表,并自动为这些属性生成getter/setter,以及序列化代码?是这样吗?您能提供一个示例,说明您希望使用哪种类型的代码吗?
    struct Attribute
    {
        virtual QString serializePlainText() = 0;
    };
    
    // Generic attribute for the most common cases
    template <typename T>
    class MandatoryAttribute : public Attribute
    {
        T value;
    
      public:
    
        std::string serializePlainText() 
        { 
            return boost::lexical_cast<std::string>(value);
        }
    };
    
    // Generic attribute for the most common cases
    template <typename T>
    class OptionalAttribute : public Attribute
    {
        boost::optional<T> value;
    
      public:
    
        bool isSet() const { return value; }
    
        std::string serializePlainText() 
        { 
            return isSet() ? 
                boost::lexical_cast<std::string>(value) :
                "";
        }
    };