学习OOP:超载 OR =操作员错误

Learning OOP: Overloading the + or = operator error

本文关键字:操作员 错误 OR 超载 OOP 学习      更新时间:2023-10-16

我想我会为看到它的其他任何人编辑。由于你们的答案,我已经修复了它。错误是因为出于某种愚蠢的原因将两个构造函数删除指针大声笑。将它们都删除,并且可以很好地编译:D

嗨,我在过去几天里一直在广泛地工作,以了解课程和运营商超载,复制构造函数等。使用Ivor Hortons Visual C 2012。

我以前已经创建了一个具有相同概念的类。

现在,在我上课的这一班上,我在班级中添加了" "answers" ="操作员过载后,我一直受到访问的侵犯。我已经看过我写过的以前的课程,这次看不到我如何做任何不同的事情。这是我一直在使用的代码:

#include <iostream>
#include <string>
using namespace std;
class Game
{
public:
static int countObj;
explicit Game(char* title = "Default title", int difficulty = 10, int players = 4)
{
    delete [] mp_title;
    mp_title = new char[strlen(title) + 1];
    strcpy_s(mp_title, strlen(title) + 1, title);
    m_difficulty = difficulty;
    m_players = players;
    m_objID = countObj;
    cout << "Object " << ++countObj << " created" << endl;
}
Game(const Game& objGame)
{
    delete [] mp_title;
    mp_title = new char[strlen(objGame.mp_title) + 1];
    strcpy_s(mp_title, strlen(objGame.mp_title) + 1, objGame.mp_title);
    m_difficulty = objGame.m_difficulty;
    m_players = objGame.m_players;
    cout << "Object " << ++countObj << " created using copy constructor" << endl;
    m_objID = countObj;
}
~Game()
{
    cout << "Destructor called on object: " << this->getObjID() << endl;
    delete [] mp_title;
}
Game operator=(const Game&& objGame)
{
    cout << "= operator used as rh expression on object: " << this->getObjID() << endl;
    delete [] mp_title;
    mp_title = new char[strlen(objGame.mp_title) + 1];
    strcpy_s(this->mp_title, strlen(objGame.mp_title) + 1, objGame.mp_title);
    return *this;
}
Game& operator=(const Game& objGame)
{
    if (this != &objGame)
    {
        cout << "= operator called on object " << this->getObjID() << endl;
        delete [] mp_title;
        size_t len = strlen(objGame.mp_title) + 1;
        mp_title = new char[len];
        strcpy_s(mp_title, len, objGame.mp_title);
        m_difficulty = objGame.m_difficulty;
        m_players = objGame.m_players;
    }
    return *this;
}
Game operator+(const Game& objGame) const 
{
    cout << "+ called" << endl;
    return Game("Default title",
                (m_difficulty + objGame.m_difficulty),
                (m_players + objGame.m_players) );
} 
char* getTitle() { return mp_title; }
void setTitle(char* title) { mp_title = title; }
int getObjID() { return m_objID; }
private:
char* mp_title;
int m_difficulty;
int m_players;
int m_objID;
};
int Game::countObj = 0;
int main()
{
Game game1("Game 1", 10, 4);
Game game2("Game 2", 5, 2);
Game game3 = game2;
game2.operator=(game3.operator+(game1));
cout << game1.getObjID() << endl << game2.getObjID() << endl;
cout << game1.getTitle() << endl << game2.getTitle() << endl;
return 0;

}

,正如我所说的,这与:

有关
game2 = game3 + game1;

因为删除该程序时,程序运行。我还希望对我可以在代码中使用的任何编码样式和约定的反馈。预先感谢。

我在调试器中遇到的错误是:0xc0000005:访问违规阅读位置0xcccccccc0

delete [] mp_title;

这将删除当时完全非初始化的指针mp_title。您在构造函数中永远不需要它(因为从定义上来说,一切都是不可分化的)。这是两个构造函数的,但没有其他。

作为通用提示,C0000005是分段故障(某种未分配的内存的访问,并且以CCCCC或CDCDCD开头的地址是Visual Studio的单次记忆的默认调试填料。

Game operator=(const Game&& objGame)

这个只能交换电流和对方的内容;您可以确保接下来的论点会破坏,以便您可以将其用作"废物处理"。无需副本,只需交换即可。

    size_t len = strlen(objGame.mp_title) + 1;
    mp_title = new char[len];
    strcpy_s(mp_title, len, objGame.mp_title);

这是Microsoft-ism。strcpy_s不如strcpy(1)那么便携,在这种情况下,您无论如何都将strlen(arg3)作为长度,这使得与使用strcpy(2)相比,头发不安全。习惯于使用strcpy,并找出何时不安全;这将有助于您防止比毯子使用strcpy_s更多的错误,而不知道您要预防哪些错误。

刚刚尝试在GCC 4.7.3(默认Ubuntu 13.04编译器)上运行它,然后删除了从构造函数中删除两个删除,它运行良好。结果是

Object 1 created
Object 2 created
Object 3 created using copy constructor
+ called
Object 4 created
= operator used as rh expression on object: 1
Object 5 created using copy constructor
Destructor called on object: 5
Destructor called on object: 3
0
1
Game 1
Default title
Destructor called on object: 3
Destructor called on object: 1
Destructor called on object: 0

看起来有点错(尤其是对象ID),但不会崩溃。

您的设置非常错误(不复制其参数),但您没有使用它,因此现在不会造成麻烦。

正如人们之前提到的那样,您应该使用std ::弦,因为它们完全阻止了这种混乱。实际上,如果您使用了这些方法,则可能可以删除大多数构造函数&amp;毁灭者并让默认生成的人为您完成工作。