帮我调试一下 - 从'const char *'到'char *'的无效转换

时间:2009-10-11 18:37:00

标签: c++ const

我根本不明白为什么会出现这个错误。

Widget.cpp: In constructor 'Widget::Widget(Generic, char*, int, int, int, QObject*)':
Widget.cpp:13: error: invalid conversion from 'const char*' to 'char*'

就Widget的构造函数而言,我没有任何'const char *'。

class Widget: public QObject {
    Q_OBJECT
    Q_PROPERTY(char *col READ getCol WRITE setCol)
    Q_PROPERTY(char *row READ getRow WRITE setRow)
    Generic visitor;
    char *_name;
    char *_widget_base;
    int _row;
    int _col;
    int _type;
    public:
    Widget(Generic visitor, char *name, int row, int col, int type, QObject *parent);
    char* widgetBase() const;
    QString getCol() const;
    void setCol(const QString &col);
    QString getRow() const;
    void setRow(const QString &row);

};

Widget::Widget(Generic v, char *name, int row, int col, int type, 
    QObject *parent = 0 ) {
    visitor = v;
    std::string str(name);
    int pos1 = str.find(":");
    int pos2 = str.rfind(":");
    _widget_base = str.substr(pos1, pos2-pos1).c_str();
    _name = name;
    _row = row;
    _col = col;
    _type = type;
}

2 个答案:

答案 0 :(得分:5)

这是const char *

str.substr(pos1, pos2-pos1).c_str();

答案 1 :(得分:4)

除了已经回答的编译器错误之外,您的代码还有其他一些问题。 (至少,假设你发布的代码接近或正是你在项目中实际使用的代码。)

即使您将_widget_base更改为const指针,这行代码也是一个问题:

_widget_base = str.substr(pos1, pos2-pos1).c_str();

substr返回一个临时字符串对象。 c_str()的结果仍归该临时字符串所有。在写入行的方式中,临时字符串对象将在执行该行后被销毁。因此,问题是_widget_base将指向已删除的内存区域,并且可以随时重复使用。

根据您传递给Widget构造函数的内容,您可能也遇到与_name类似的问题。

因此,您可以使用_widget_base_name

执行以下三项操作之一

1)自己动态分配内存,使其不受任何其他对象的管理。

std::string temp = str.substr(pos1, pos2-pos1);
_widget_base = new char[temp.length()+1];
strcpy(_widget_base, temp.c_str());

当然,您还需要在Widget的析构函数中管理这个内存的删除。如果在Widget存在时可以更改此值,也可能重新分配。

2)使这些成员变量成为字符数组而不是指针。这样,内存是Widget的永久部分,不需要进行管理。当然,您还必须确定阵列的大小。

char _name[a big enough value];
char _widget_base[a big enough value];

然后:

std::string temp = str.substr(pos1, pos2-pos1);
strcpy(_widget_base, temp.c_str());

3)使这些成员变量成为字符串对象。

std::string _name;
std::string _widget_base;

然后:

_widget_base = str.substr(pos1, pos2-pos1);

这种方式是最优选的,因为它是最强大且最不容易出错的。您没有内存可以直接管理,也不用担心太大而无法容纳的值。