首页 > 解决方案 > c++ VS 2010 到 VS 2019 升级。升级后需要 const 参数列表。为什么?

问题描述

非常长期的 C++ 程序员。我刚刚从 Visual Studio 2010 升级到 Visual Studio 2019。升级后,使用 VS 2010 编译正常的程序无法使用 VS 2019 编译,错误 C3848。使用 std::set 发生故障,当与类一起使用时需要一个比较函数,用 operator() 实现。C3848 错误表示我的类对象的签名与 std::set 中的签名不匹配,并且不匹配是一个签名具有 const 而另一个没有。

我已经有了一个非常好的解决方法,即在我的比较函数的参数列表之后添加 const。我可能应该宣布胜利并继续前进,因为我有一个解决方案,但这个解决方案对我来说毫无意义。关于这种情况的所有文档都说参数列表后面的 const 适用于“this”变量,例如,它允许定义两个成员方法,一个用于“this”变量为常量时,一个用于“this”变量时变量不是常数。这种解释对我来说毫无意义的原因是我的小比较函数没有“this”变量——或者至少没有我知道的变量。

我的比较函数的基本结构是

class Mycomp
{
  public:
      bool operator() (const Myclass& x, const Myclass& y){... }
};

如果 x 按顺序在 y 之前返回 true,否则返回 false。Mycomp 不引用任何类型的“this”变量,只引用参数 x 和 y。在使用诸如 std::set、std::vector、std::sort 和 C++ 标准库中的许多其他服务之类的东西时,此类函数非常常见,而我编写此类代码已有近 30 年的历史。这是我第一次遇到这个问题。

为了完成这个故事,std:set 被定义为

    std::set<Myclass,Mycomp> the_set; // the name of the set can be
                                      // anything, so I made be it
                                      // be "the_set"

到此为止,没有编译错误。当我尝试将某些内容插入集合时会发生编译错误。

    Myclass an_object;    // instantiate a member of the class
    // code goes here to put some data into the_object
    the_set.insert(an_object); // insert the object into the set

在这种情况下,“insert”是 std::set 类的成员方法,并且我的比较函数与我在实例化“the_set”时称为“the_set”的集合相关联。编译错误发生在插入中,而不是在比较函数的定义中,也不是在实例化 std::set 时。在任何情况下,解决方法是将 const 添加到比较函数中,即,

    class Mycomp
{
  public:
      bool operator() (const Myclass& x, const Myclass& y) const {... }
    };        

我想这让我想知道以下内容。通常,您有具有“this”变量的非静态成员方法,并且您有没有“this”变量的静态成员方法。那么 operator() 和 operator<() 等是静态的还是非静态的呢?我从未有过具有“this”变量的运算符类型成员方法,但我也从未将运算符类型成员方法声明为静态。那么发生了什么?为什么在没有“this”变量的情况下必须将“this”变量声明为常量?

标签: c++

解决方案


我从来没有一个操作员类型的成员方法有一个“this”变量,但我也从来没有将一个操作员类型的成员方法声明为静态的。

你这么说好像有两个以上的选择。如果一个函数是一个类型的成员,那么它要么是静态的,要么是非静态的。如果你没有写static在成员声明/定义中,那么它有一个this指针。无论您是否使用它,它都在那里。

您的operator()重载是在 的实时实例上调用的Mycomp。因此,它需要一个作为指针。因此,该函数的执行与该对象之间的关系很重要。以前,set不关心函数是否修改了实例。但是,这样做是未定义的行为,因为set允许创建和销毁它认为合适的实例。

C++ 委员会决定简单地禁止比较运算符修改对象,而不是将此类修改保留为不可检测的 UB。


推荐阅读