Russian Qt Forum
Ноябрь 26, 2024, 02:28 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: Как правильно создать наследника QObject?  (Прочитано 25904 раз)
Shilo
Гость
« Ответ #15 : Август 26, 2009, 12:17 »

Лучше убрать const в сигнатуре, потому что некоторые авторы по с++ не рекомендуют использовать const_cast для "обезвреживания" const (почему не знаю, если кто-то отпишет буду признателен).
потому как сигнатура подразумевает, что объект не будет меняться, а ты внутри функции берешь и снимаешь это ограничение.
А чем это может быть чревато? Если я сделаю вот так
Код
C++ (Qt)
void ProjectProperties::setCoordinateSystem(const CoordinateSystem *newCoordinateSystem)
{
   curCoordinateSystem = const_cast<CoordinateSystem*>(newCoordinateSystem);
}
 
это ведь не будет означать, что *newCoordinateSystem в дальнейшем можно изменить внутри этой функции. Или я ошибаюсь?
Записан
spirit
Гость
« Ответ #16 : Август 26, 2009, 12:31 »

для наглядности
Код
C++ (Qt)
...
void ProjectProperties::setCoordinateSystem(const CoordinateSystem *newCoordinateSystem)
{
curCoordinateSystem = const_cast<CoordinateSystem*>(newCoordinateSystem);
curCoordinateSystem->setName("newName");
}
...
CoordinateSystem cs;
cs.setName("oldName");
qDebug() << cs.name();//oldName
ProjectProperties pp;
pp.setCoordinateSystem(&cs);
qDebug() << cs.name();//newName
...
 
Записан
spirit
Гость
« Ответ #17 : Август 26, 2009, 12:35 »

вот так сделай
Код
C++ (Qt)
...
public slots:
   const CoordinateSystem* coordinateSystem() const {return curCoordinateSystem;}
   void setCoordinateSystem(const CoordinateSystem *newCoordinateSystem)
{
curCoordinateSystem = newCoordinateSystem;
}
 
private:
   const CoordinateSystem* curCoordinateSystem;
...
 
Записан
Shilo
Гость
« Ответ #18 : Август 26, 2009, 14:59 »

Вариант с const_cast работает, хотя выглядит несколько грубовато...

А вот это
вот так сделай
Код
C++ (Qt)
...
public slots:
   const CoordinateSystem* coordinateSystem() const {return curCoordinateSystem;}
   void setCoordinateSystem(const CoordinateSystem *newCoordinateSystem)
{
curCoordinateSystem = newCoordinateSystem;
}
 
private:
   const CoordinateSystem* curCoordinateSystem;
...
 
не годится. Ведь в таком случае  curCoordinateSystem становится константой. И как же я ему буду присваивать новое значение? Поправте меня, если я не прав.
Записан
spirit
Гость
« Ответ #19 : Август 26, 2009, 15:04 »

дык, ты определись, нужно ли тебе менять значение объета или нет.
если нет, то используй такую сигнатуру:setCoordinateSystem(CoordinateSystem *newCoordinateSystem)
это и будет правильным подходом, нежели чем использовать приведение типов.
Записан
Shilo
Гость
« Ответ #20 : Август 26, 2009, 15:26 »

Я давно определился. Мне нужно менять значение CoordinateSystem *curCoordinateSystem - приватного члена класса ProjectProperties. Если этот член объявить const CoordinateSystem *curCoordinateSystem , то как же я его буду менять?
С другой стороны, этот член меняется спомощью public слота void setCoordinateSystem(const CoordinateSystem *newCoordinateSystem). В качестве параметра этой функции выступает CoordinateSystem *newCoordinateSystem. Сам этот параметр изменяться не должен. Поэтому используется модификатор const.
Вроде все гладко, но при этом необходимо применять const_cast.
Код
C++ (Qt)
void ProjectProperties::setCoordinateSystem(const CoordinateSystem *newCoordinateSystem)
{
   curCoordinateSystem = const_cast<CoordinateSystem*>(newCoordinateSystem);
}
 
Вот вроде и все. Если другого решения нет, то вопрс закрыт.
Записан
spirit
Гость
« Ответ #21 : Август 26, 2009, 15:27 »

Первый вариант: Дык мне надо, чтоб передаваемый в функцтю объект точно не изменялся.
тогда к чему вот это?
Записан
spirit
Гость
« Ответ #22 : Август 26, 2009, 15:29 »

убери const из ProjectProperties::setCoordinateSystem и тогда будет понятно,
что объект будет меняться, но не обязательно именно в этом методе.
если же оставлять const, то будет сбивать с толку изменение объекта (пример я уже приводил с переустановкой имени объекта).
Записан
Shilo
Гость
« Ответ #23 : Август 26, 2009, 15:31 »

Первый вариант: Дык мне надо, чтоб передаваемый в функцтю объект точно не изменялся.
тогда к чему вот это?
Видимо я не очень точно выразился. Вместо "передаваемый в функцтю объект" нужно было сказать "параметр функции"... Сори В замешательстве
Записан
spirit
Гость
« Ответ #24 : Август 26, 2009, 15:32 »

Первый вариант: Дык мне надо, чтоб передаваемый в функцтю объект точно не изменялся.
тогда к чему вот это?
Видимо я не очень точно выразился. Вместо "передаваемый в функцтю объект" нужно было сказать "параметр функции"... Сори В замешательстве
бывает Улыбающийся. ну в общем я бы не юзал приведение, а убрал бы const из сигнатуры.
Записан
Shilo
Гость
« Ответ #25 : Август 26, 2009, 15:39 »

IMHO const в сигнатуре функции не только предотвращает изменение параметра функции в процессе ее выполнения на этапе компилирования (тут все идет прахом из-за применения const_cast), но и информирует об этом программиста, читающего листинг.
Записан
spirit
Гость
« Ответ #26 : Август 26, 2009, 15:42 »

мне бы не было понятным, почему после передачи объекта как константый указатель в метод, он затем поменял состояние...
Записан
Shilo
Гость
« Ответ #27 : Август 26, 2009, 15:57 »

spirit, очевидно вы не совсем вникли. Метод должен менять private член объекта, для которого этот метод вызван. Но он не должен менять объек, который передается в качестве параметра этого метода. Оба они (и private член и параметр метода) являются объектами одного класса. В данном случае класса CoordinateSystem. Сам метод описан в классе ProjectProperties.
Я бы не поднимал эту тему, если бы не одно НО. Класс CoordinateSystem является потомком QObject. В QObject конструктор копирования и оператор = объявлены private. Если бы не это обстоятельство, то можно было бы в качестве аргумента метода вместо указателя использовать ссылку.

Короче всм СПАСИБО, я разобрался.
Записан
Shilo
Гость
« Ответ #28 : Август 27, 2009, 10:22 »

Нет не разобрался. Тут может возникнуть проблема при передаче параметра как указателя.
Допустим где-то в программе я создал временную переменную cs класса CoordinateSystem как указатель. Далее я передаю эту переменную в метод ProjectProperties::setCoordinateSystem. А затем удаляю переменную cs и освобождаю память. Если в методе ProjectProperties::setCoordinateSystem использовать код
Код
C++ (Qt)
void ProjectProperties::setCoordinateSystem(const CoordinateSystem *newCoordinateSystem)
{
   if (newCoordinateSystem){
     curCoordinateSystem = const_cast<CoordinateSystem*>(newCoordinateSystem); //так нельзя!
   };
}
 
то в curCoordinateSystem будет содержаться адрес по которому память уже освобождена. Последствия всем понятны.
И еще ньюанс. Если не удалять временную переменную, то мы получаем доступ к закрытому члену curCoordinateSystem что не есть правильно.
Значит выше приведенный код неприемлим. Вместо него надо скопировать ЗНАЧЕНИЯ каждого поля из параметра функции в наш закрытый член класса. По сути это альтернатива оператоа =. Какого ляда тролли объявили его закрытым в QObject я не знаю. Но думаю у них есть на это причины.
Прилагаю тестовый проектик с наследованием от QObject. Просмотрите, может я чего не так наваял. А может есть вообще радикально другой способ.
« Последнее редактирование: Август 27, 2009, 10:25 от Shilo » Записан
spirit
Гость
« Ответ #29 : Август 27, 2009, 10:32 »

для этого есть QPointer.
Код
C++ (Qt)
...
QPointer<CoordinateSystem> curCoordinateSystem;
...
 
и потом проверяй указатель
Код
C++ (Qt)
...
if (!curCoordinateSystem)
  return;
...
 
Записан
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.188 секунд. Запросов: 21.