Помогите мне отладить это - неверное преобразование из 'const char *' в 'char *' - PullRequest
0 голосов
/ 11 октября 2009

Я просто не понимаю, почему эта ошибка появляется.

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

Нигде у меня нет 'const char *' в терминах конструктора Widget.

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 ]

5 голосов
/ 11 октября 2009

Это const char * значение

str.substr(pos1, pos2-pos1).c_str();
4 голосов
/ 12 октября 2009

Помимо ошибки компилятора, на которую уже есть ответ, у вашего кода есть некоторые другие проблемы. (По крайней мере, если предположить, что код, который вы разместили, близок или точно соответствует тому, что вы фактически используете в своем проекте.)

Даже если вы измените _widget_base на постоянный указатель, эта строка кода является проблемой:

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

substr возвращает временный строковый объект. Результат c_str() все еще принадлежит этой временной строке. И как пишется эта строка, временный строковый объект будет уничтожен после выполнения строки. Таким образом, проблема заключается в том, что _widget_base останется указывающим на область памяти, которая была удалена и которая может быть использована повторно в любое время.

У вас также могут быть похожие проблемы с _name в зависимости от того, что вы передаете в конструктор Widget.

Так что вы могли бы сделать одну из трех вещей с _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());

Конечно, вам также необходимо управлять удалением этой памяти в деструкторе вашего виджета. А также возможно перераспределение, если это значение может быть изменено, пока существует виджет.

2) Сделать эти переменные-члены символьными массивами вместо указателей. Таким образом, память - это постоянная часть виджета, которой не нужно управлять. Конечно, вам также нужно определить, насколько большой размер для массивов.

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);

Этот способ наиболее предпочтителен, поскольку он наиболее надежен и наименее подвержен ошибкам. У вас нет памяти для непосредственного управления, и вам не нужно беспокоиться о значениях, которые слишком велики для хранения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...