编译器错误C2280,尝试引用已删除的函数operator=。

3
我可以为您提供中文翻译服务,以下是需要翻译的内容:

我正在编写一个大富翁游戏。我非常喜欢使用排序函数来生成漂亮干净的输出,例如按组对玩家拥有的财产进行排序。

首先,这是我的财产排序函数:

bool propertySort(Property a, Property b) { return a.getGroup() <  b.getGroup(); }

现在,用户拥有这些属性的列表。
#pragma once
#include <string>
#include <vector>
#include "Dice.h"
#include "Property.h"

class Player
{
public:
    ...
private:
    int curMoney{ 1500 };
    int curLocation{ 0 };
    int playerNum{ 0 };
    std::string name;
    std::vector<Property> ownedProperties{};
    int curDiceRoll;
};

正如您所看到的,它是一个私有属性,向下初始化为0个属性。

因此,在我的主要属性排序器中,我将显示属性到板上供玩家查看,但排序函数不断给我提供错误C2280。我知道这正是排序函数引发此错误,因为如果我注释掉排序行,程序就可以正常运行。我确定这是我作为初学者程序员所不知道的显而易见的东西。如果有人能提供关于这是什么的见解,那就太好了,谢谢!

void viewProperties(Player& p)
{
    string prompt = "Select a player to view their properties";
    vector<string> playerNames{};
    for (Player p : players)
    {
        playerNames.push_back(p.getName());
    }
    Menu propertiesMenuSelection{ prompt, playerNames };
    vector<Property> propertiesOfSelectedPlayer = players[propertiesMenuSelection.getChoice()].getOwnedProperties();
    sort(propertiesOfSelectedPlayer.begin(), propertiesOfSelectedPlayer.end(), propertySort);

    system("CLS");

如果有帮助的话,这里是Property类

#pragma once
#include "Space.h"
#include <array>
#include <vector>

extern std::vector<Player> players;
class Property : public Space
{
public:
    Property(std::string name, std::vector<int> values);
    ~Property();
    void run(Player&) override;
    std::vector<std::string> boardOut() const override;
    std::string getName() const override;
    ...
private:
    std::string name;
    int group;
    int price;
    int buildingCost;
    int buildings;
    Player* ownerPtr = nullptr;
    std::array <int, 6> rent;
    const std::array <std::string, 10> groups{ "Brown", "Light Blue", "Pink", "Orange", "Red", "Yellow", "Green", "Dark Blue", "Railroad", "Utility" };
};

这是一个非常简单的空间类,正如您所要求的。
#pragma once
#include <string>
#include <vector>

class Player;

class Space
{
public:
    virtual void run(Player&) = 0;
    virtual std::string getName() const = 0;
    virtual std::vector<std::string> boardOut() const = 0;
};

enter image description here


2
const std::array - 这个成员变量可能是为什么没有可用的复制功能。 - PaulMcKenzie
1
因为你不能给一个const变量赋值。愚蠢的例子:https://ideone.com/AieNNX - user4581301
1
这是一个更好的版本,带有更易读的错误信息:https://ideone.com/6RiXzJ - user4581301
1
现在我想起来了,这是一个罕见的情况,在这种情况下,您需要一个分配运算符,但不需要其他三个。很酷。现在我有了一个例子! - user4581301
2
@Alex -- 简单来说,编译器无法确定你对该成员变量的操作意图,因为它是const的。这是一篇旧文,但与此相关的文章,来自Dr. Dobbs - PaulMcKenzie
显示剩余5条评论
1个回答

7

被删除的函数是赋值运算符。由于const成员groups不能被赋值,因此无法对Property进行赋值。最合理的解决方案是将groups声明为static,以便Property的所有实例共享它,不需要进行赋值。例如:

static const std::array <std::string, 10> groups;

需要在类定义之外为groups分配和初始化存储空间:

const std::array <std::string, 10> Property::groups{ "Brown", "Light Blue", "Pink", 
                                                     "Orange", "Red", "Yellow", "Green", 
                                                     "Dark Blue", "Railroad", "Utility" };

简述

赋值运算符的默认行为是将源对象的所有成员复制到目标对象中,而不会对复制进行任何智能处理。这意味着一个非常简单的例子:

class test
{
public:
    const int a = 10;
};

将生成相当于的内容
test& operator=(const test & src)
{
    a = src.a;
    return *this;
}

这是不可能的,因为aconst,即使没有更改也无法改变。

您可以添加自己的赋值运算符。

test& operator=(const test & src)
{
    // deliberately does not assign a = src.a
    return *this;
}

但唯一需要这样做的原因是,如果在初始化时无法更改a的值。如果您无法更改a,则所有test的实例都具有相同的a值,而且a可能就像是一个static成员一样。
两个test具有不同a值的失败示例:
int main()
{
    test a{11}; // a const variable cannot be changed after initialization, 
                // but this initializes a to 11.
    test b;     // uses the default of 10

    std::cout << a.a << ',' << b.a; // output 11,10
    a = b; //this can't really be be done. a can never equal b
}

太完美了!解释得非常好。那个静态解决方案正是我所需要的,并且已经实施了,非常感谢! - Alex
1
@Alex 没问题。对你来说已经太晚了,但希望下一个遇到这个问题的人能找到它。 - user4581301
我的想法完全一样,如果其他人遇到这个错误,可能会非常困惑,特别是在使用类似排序的功能时突然出现。希望他们能找到这个问题,并查看你的答案。也许他们会意识到无限制地使用非静态常量是多么危险。对我来说,这是一个很好的教训,希望对其他人也有帮助! - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接