2

我正在为 C++ 课做家庭作业,遇到了一些困难。由于 item::operator= 调用的 item::name() 中“使用了大小为 8 的未初始化值”和“大小为 8 的无效读取”,我的程序出现了段错误。

#ifndef ITEM_H
#define ITEM_H

const double WEIGHT_DEFAULT = 1.0;
const int ITEM_NAME_LENGTH = 30;

class item {
public:
    // Constructors and deconstructor
    item();
    item(char* nme, double weight);
    virtual ~item();

    // Copy constructor
    item(const item& itm);

    // Overload assignment operator
    const item& operator=(const item& itm);

    // Overload inequality operator
    bool operator!=(const item&) const;

    // Mutators and accessors
    const char* name(void) const;
    double weight(void) const;
    void weight(double wght);
    void name(char* nme);

protected:
private:
    char* m_name;
    double m_weight;
};

#endif // ITEM_H

以下是我认为有问题的部分实现:

... 

const item& item::operator=(const item& itm)
{
    if (strcmp(this->name(), itm.name()) != 0)
    {

        this->weight(itm.weight());
        strcpy(m_name, itm.name());
    }

    return *this;
}

const char* item::name(void) const {
    return m_name;
}

...

如您所见,部分任务是使用 c 字符串,因此我被混乱的细节所困扰。我对指针和类的理解是,当同时使用两者时,我们需要实现析构函数、复制构造函数和重载赋值运算符。我已经完成了以上所有。我在 Stack Overflow 上查看了有关复制和交换习语的一些信息,并尝试实现它,但也无法让它与我的代码一起使用。

我的大脑变得疲惫不堪,试图弄清楚我哪里出错了。有人可以告诉我我错过了什么吗?

谢谢!


编辑

以下是构造函数、析构函数等:

item::item() {
    //ctor

    m_name = new char[ITEM_NAME_LENGTH];
    strncpy(m_name, " ", ITEM_NAME_LENGTH - 1);
    this->weight(WEIGHT_DEFAULT);

    return;
}

item::item(char* nme, double wght) {
    m_name = new char[ITEM_NAME_LENGTH];

    strncpy(m_name, nme, ITEM_NAME_LENGTH - 1);

    // We want to check for a rational value being
    // passed in to weight. In theory, an item has
    // to have *some* kind of weight, so we check
    // for a weight of 0. If a weight of 0 has been passed in,
    // we instead initialize the item's weight to the
    // default weight (set in the header file).
    if (wght > 0.0) {
        this->weight(wght);
    } else {
        this->weight(WEIGHT_DEFAULT);
    }

    return;
}

item::~item() {
    //dtor

    // TODO: We need to clean up any variables here.
    delete[] m_name;
}

item::item(const item& itm) {
    // copy ctor
    this->weight(itm.weight());
    strncpy(m_name, itm.name(), ITEM_NAME_LENGTH - 1);

}

const item& item::operator=(const item& itm)
{
    if (strcmp(this->name(), itm.name()) != 0)
    {

        this->weight(itm.weight());
        strcpy(m_name, itm.name());
    }

    return *this;
}

bool item::operator!=(const item& itm) const
{
    return (strcmp(m_name, itm.name()) != 0);
}

编辑 2

现在我已经停止尝试动态分配名称 c 字符串,我在权重函数上遇到内存错误......

double item::weight(void) const {
    return m_weight;
}

void item::weight(double wght)
{
    m_weight = wght;
}
4

2 回答 2

1

首先,您不需要显式地return;fromvoid语句。

第二:创建复制构造函数时,您需要分配将用于保存该构造函数的内存的空间,就像您为常规构造函数所做的那样。

在你的复制构造函数中试试这个:

m_name = new char[ITEM_NAME_LENGTH];

编辑:为了完整起见,这就是我的“似乎正在工作”的代码:

#include <stdio.h>
#include <string.h>


const double WEIGHT_DEFAULT = 1.0;
const int ITEM_NAME_LENGTH = 30;

class item {
public:
    // Constructors and deconstructor
    item();
    item(char* nme, double weight);
    virtual ~item();

    // Copy constructor
    item(const item& itm);

    // Overload assignment operator
    const item& operator=(const item& itm);

    // Overload inequality operator
    bool operator!=(const item&) const;

    // Mutators and accessors
    const char* name(void) const;
    double weight(void) const;
    void weight(double wght);
    void name(char* nme);

protected:
private:
    char* m_name;
    double m_weight;
};


const item& item::operator=(const item& itm)
{
    if (strcmp(this->name(), itm.name()) != 0)
    {

        m_name = new char[ITEM_NAME_LENGTH];
        this->weight(itm.weight());
        strcpy(m_name, itm.name());
    }

    return *this;
}

const char* item::name(void) const {
    return m_name;
}

double item::weight(void) const {
    return m_weight;
}

void item::weight(double wght) {
    m_weight = wght;
}

item::item() {
    //ctor

    m_name = new char[ITEM_NAME_LENGTH];
    strncpy(m_name, " ", ITEM_NAME_LENGTH - 1);
    this->weight(WEIGHT_DEFAULT);

    return;
}

item::item(char* nme, double wght) {
    m_name = new char[ITEM_NAME_LENGTH];

    strncpy(m_name, nme, ITEM_NAME_LENGTH - 1);

    // We want to check for a rational value being
    // passed in to weight. In theory, an item has
    // to have *some* kind of weight, so we check
    // for a weight of 0. If a weight of 0 has been passed in,
    // we instead initialize the item's weight to the
    // default weight (set in the header file).
    if (wght > 0.0) {
        this->weight(wght);
    } else {
        this->weight(WEIGHT_DEFAULT);
    }

    return;
}

item::~item() {
    //dtor

    // TODO: We need to clean up any variables here.
    delete[] m_name;
}

item::item(const item& itm) {
    // copy ctor
    this->weight(itm.weight());
    m_name = new char[ITEM_NAME_LENGTH];
    strncpy(m_name, itm.name(), ITEM_NAME_LENGTH - 1);

}

bool item::operator!=(const item& itm) const
{
    return (strcmp(m_name, itm.name()) != 0);
}


int main(int argc, char* argv[])
{
    item i("test",2.0);
    item b = i;
    item c;
    item d = c;
    return 0;
}
于 2013-01-23T05:22:45.617 回答
1

我想使用 std::string 作为练习的一部分,对吧?否则,这就是字符串处理的方式。您可以尝试的另一件事是避免字符串的动态分配。相反,只需使用char m_name[ITEM_NAME_LENGTH];. 顺便说一句:那是什么长度?如果它是名称中的最大字符数,则需要一个+1作为终止 NUL 的字符。

也就是说,还有一件事:在赋值运算符中,您比较if(this != &other),即比较两个对象的地址。关键是要避免容易出错的自我分配。您的作业检查名称是否不同,然后才复制名称和重量。如果只是重量不同呢?

于 2013-01-23T06:23:41.093 回答