代码之家  ›  专栏  ›  技术社区  ›  f0b0s

与常量成员交换方法

  •  6
  • f0b0s  · 技术社区  · 15 年前

    我想为我的类实现一个swap()方法(我们称之为a),以生成copy和swap操作符=。据我所知,swap方法应该通过交换类的所有成员来实现,例如:

    class A 
    {
      public:
        void swap(A& rhv) 
        {
            std::swap(x, rhv.x);
            std::swap(y, rhv.y);
            std::swap(z, rhv.z);
        }
      private:
        int x,y,z;
    };
    

    但是如果我有警察我该怎么办?我不能调用std::swap来代替它,所以我不能对a::swap()进行编码。

    编辑:实际上我的课有点复杂。我想序列化和反序列化它。const成员是一段在此对象中不会更改的数据(例如ID)。所以我想写一些东西,比如:

    class A
    {
      public:
        void Serialize(FILE* file) const
        {
            fwrite(&read_a, 1, sizeof(read_a), file);
        }
    
        void Deserialize(FILE* file) const
        {
            size_t read_a;
            fread(&read_a, 1, sizeof(read_a), file);
            A tmp(read_a);
            this->Swap(tmp);
        }
    
     private:
       const size_t a;
    };
    

    并称之为代码:

    A a;
    FILE* f = fopen(...);
    a.Deserialize(f);
    

    我为如此含糊的措辞感到抱歉。

    7 回复  |  直到 7 年前
        1
  •  4
  •   Hassan Syed    15 年前

    晚上睡个好觉之后,我认为最好的答案是使用一个指向常量值的非常量指针——毕竟这些都是您试图捕获的语义。

        2
  •  8
  •   Tyler McHenry    15 年前

    我认为您真正想要的是拥有一个内部数据结构,您可以轻松地在对象之间进行交换。例如:

    class A 
    {
       private:
    
         struct A_Data {
           int x;
           int y;
           const int z;
    
           A_Data(int initial_z) : z(initial_z) {}
        };
    
        std::auto_ptr<A_Data> p_data;
    
      public:
    
         A(int initial_z) : p_data(new A_Data(initial_z)) {}
    
         void swap(A& rhv) {
            std::swap(p_data, rhv.p_data);
         }
    };
    

    这保持了 z 任何实例中的值常量 A 对象内部数据,但可以交换两个 对象(包括常量 Z 值)不违反常量正确性。

        3
  •  3
  •   DigitalZebra    15 年前

    一个好的设计原则是把你的对象设计成 不变的 . 这意味着对象一旦创建就不能更改。要“更改”对象,必须复制该对象并确保更改所需的元素。

    也就是说,在这种情况下,您应该考虑使用复制构造函数来复制要交换的对象,然后实际交换对该对象的引用。我可以理解,仅仅改变引擎盖下对象的元素是很诱人的,但是最好是复制一个对象并用 新建 对象。这能让你避开任何便秘。

    希望这有帮助。

        4
  •  1
  •   Thomas Matthews    15 年前

    我建议您使用指向实例的指针。指针交换比 class struct .

    唯一的方法 互换 常量值是创建另一个对象,或者 clone 当前对象。

    给出了一个结构:

    struct My_Struct
    {
      const unsigned int ID;
      std::string        name;
      My_Struct(unsigned int new_id)
        : ID(new_id)
      { ; }
    };
    

    我的理解是你想交换 My_Struct 上面。您可以复制可变(非常量)成员,但不能复制 const 成员。唯一改变 康斯特 成员将使用 康斯特 成员。

    也许你需要重新考虑你的设计。

        5
  •  0
  •   SDReyes    15 年前

    imho您必须考虑不交换const成员。

    我认为你可以考虑在你的方法中使用反射。所以你不需要维护函数。

        6
  •  0
  •   Mark Ransom    15 年前

    这就是为什么 const_cast 已创建。记住不要把脚踢开。

    编辑: 好吧,我承认-警察局根本不是为这个问题而设的。这可能适用于你的编译器,但你不能指望它,如果恶魔从你鼻孔里飞出来,请不要怪我。

        7
  •  0
  •   Kahler    7 年前

    这是未定义的行为。

    Reference/reason: CppCon 2017: Scott Schurr “Type Punning in C++17: Avoiding Pun-defined Behavior, @24m52s +- ”

    我的解释,举例来说:

    假设您创建一个类型为的对象 T 有一些 const 成员。可以将此对象作为对函数的非常量引用传递 f(&T) 这是在操纵它,但你会预料到 康斯特 成员在调用后保持不变。 swap 可以在非常量引用中调用,并且可以在函数内部调用 f 打破了 康斯特 调用者的成员。

    代码中使用的每个部分 掉期 必须声明类型为的对象 T 被交换不属于 康斯特 成员被假定为常量。这是不可能自动验证的*。

    *我只是假设这是不可能验证的,因为这似乎是中止问题不可决定性的延伸。

    推荐文章