【问题标题】:Const Class Member Copy ConstructorConst 类成员复制构造函数
【发布时间】:2014-09-30 23:34:14
【问题描述】:
#include "booking.h"
#include <iostream>
booking::booking (  const std::string p_title,  const std::string p_notice,  const category p_category,  const person p_person,  const booking::Type p_type,  const double p_value ) :
m_type{ p_type },
m_title{ p_title },
m_notice{ p_notice },
m_person{ p_person },
m_category{ p_category },
m_value { p_value }
{
    std::cout << "Booking was created" << std::endl; // Debug Message
}

这些是文件(我认为必须知道的所有内容)

#pragma once
#include <string>
#include "person.h"
#include "category.h"
class booking
{
public:
    enum Type { TYPE_REVENUE, TYPE_EXPENDITURE };
    booking ( const std::string p_title, const std::string p_notice, const category p_category, const person p_person, const booking::Type p_type, const double p_value ); //Basic Constructor
    ~booking();
    Type GetType ( );
    std::string GetTitle ( );
    std::string GetNotice ( );
    category GetCategory ( );
    double GetValue ( );

private:
     Type m_type;
     std::string m_title;
     std::string m_notice;
     category m_category;
     person m_person;
     double m_value;

};

如果我将类成员之一(如 m_type 或 double 值,不管哪个)放入 const,它会引发以下错误:

Fehler 1 错误 C2280:booking &amp;booking::operator =(const booking &amp;):试图引用已删除的函数 C:\Program Files (x86)\Microsoft Visual C++ Compiler Nov 2013 CTP\include\utility 53

我不明白为什么编译器会抱怨复制构造函数以及基本上是什么问题。

【问题讨论】:

  • 通过 const 引用传递字符串,可能还有你的人和类别。
  • 除极少数情况外,我从不将成员变量设为 const。相反,如果我不希望它改变,我将对象本身设为 const。

标签: c++ constructor copy


【解决方案1】:

当你声明一个const成员时,编译器不会生成一个默认的赋值操作符(它不知道在赋值过程中如何处理这个成员,毕竟它是 const ?) ,您必须自己编写赋值运算符。

注意:

  • 通过引用 const 向您传递参数。

【讨论】:

  • “你必须自己编写赋值运算符”这样的运算符很可能会非常令人惊讶,而且不应该存在。
  • @BarryTheHatchet:的确,赋值运算符不太可能对具有const 数据成员的类有意义,但在某些情况下。例如,索引std::vector&lt;bool&gt; 会生成一个代理,可以分配给它以更改位集状态。我不知道它是否有任何const 成员,但它可能有。并且仍然有意义。
  • @Cheersandhth.-Alf:当然,有可能,这就是我说“最有可能”的原因。虽然不推荐将std::vector&lt;bool&gt; 作为类设计的示例:P
【解决方案2】:

operator= 不是复制构造函数,它是 赋值运算符

const 对象无法更新,因此您无法在赋值运算符中修改该对象。

如果您不声明自己的赋值运算符,编译器会为您生成一个按成员进行复制的运算符。但是如果有 const 成员,这就不行了,所以它毕竟不能生成赋值运算符。 (在 C++11 中,这称为具有 deleted 赋值运算符)。

最后,如果您有一些代码尝试使用赋值运算符,那么您会收到有关尝试使用已删除的赋值运算符的错误。一些标准库容器或算法要求存在赋值运算符。您没有显示所有代码,但您会尝试在某个地方执行需要分配的操作。

【讨论】:

    【解决方案3】:

    您不能(合理地)分配给具有const 成员的类的对象。

    这就是为什么您会收到关于复制赋值运算符的错误

    您没有收到有关复制构造函数的投诉。


    在其他新闻中:

    • 在 C++ 中,所有大写名称都是宏的约定。如果它们用于其他任何东西(例如常量,如 Java 中的),那么您会增加名称冲突和无意文本替换的风险。此外,这是一个令人眼花缭乱的东西,被许多人视为特别强调。 Java 没有预处理器。 C++ 确实有一个。

    • 一般来说,传递非基本类型参​​数作为对const 的引用是个好主意(您只添加了const)。对于复制的大参数,有一些额外的注意事项。在 C++11 中,这些最好按值传递和移动。

    • 应将简单的“getter”成员函数声明为const,以便可以在const 对象上调用它们。

    关于受 Java 启发的 Get 前缀,请考虑 GetSin(u)+GetCos(v)sin(u)+cos(v)。在 Java 中,Get 前缀对于使用自省的工具可能具有一定的价值。 Java 有自省功能。 C++ 没有自省。所采用的约定应该更好地适应所使用的语言。

    【讨论】:

    • 嗯,我将所有大写字母用于枚举键和非宏 const。这是一个品味问题。我承认由于碰撞风险,这有点傻。
    • “在 C++11 中,这些最好按值传递并移动。” 仅当您不再需要原来的...要观察该值,总体而言,通过 const 引用传递仍然非常可取。
    • @BarryTheHatchet:将 ref-to-const 形式参数类型用于要复制的大参数也是有一些正当理由的。然而,“只有在你不再需要原件时才[传值并移动]”不是这样的理由。因为没有意义(对实际参数没有影响),抱歉。
    • 肯定这样的原因,因为如果你确实仍然需要原来的那么按值传递和移动完全破坏你的程序。对不起。
    • @MikeMB:哦,天哪。不,我当然不知道。感谢您的链接。
    【解决方案4】:

    引用这个thread,关于带有const成员的复制构造函数,

    复制构造函数的一般形式是,

    class Foo {
    Foo( const Foo& f ) :
      mem1( f.mem1 ), mem2( f.mem2 ) /* etc */
    {}
    };
    

    其中mem1和mem2是Foo的数据成员,可以是const 成员、非常量成员、常量引用或非常量引用。

    【讨论】:

      猜你喜欢
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-10
      • 2019-03-15
      • 2021-09-04
      相关资源
      最近更新 更多