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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Для чего нужно возвращать константное значение в методах?  (Прочитано 10663 раз)
billygates
Гость
« : Май 09, 2011, 07:15 »

Привет,

Когда может потребовать такое:
Код
C
const std::string myMethod();
вместо
Код
C
std::string myMethod();
? Ведь все равно возврат происходит по значению. Если бы по ссылке -- то было бы понятно.

Спасибо.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Май 09, 2011, 08:58 »

Потребоваться может в тех же случаях что и со ссылкой, напр
Код
C++ (Qt)
const sring appPath = GetAppPath();
 
Не хотим чтобы appPath затем менялось - это ошибка. Но возвращать его по ссылке неудобно - если такой переменной нет. Пришлось бы городить как-то так
Код
C++ (Qt)
const string & GetAppPath( void )
{
static string thePath;
thePath = argv[0];
 ...
return thePath;
}
 


Записан
Sancho_s_rancho
Гость
« Ответ #2 : Май 09, 2011, 11:02 »

2 Igors
Что-то я вашего примера не понял. Может ,конечно, праздники так действуют.
Вы инициализируете константу. Все равно, что справа возвращается const или не const объект.  От этого вашему appPath не холодно, не  жарко.

Разница есть в таком случае:
Код:
struct foo
{
void bar() {}
void barfoo() const {}
};

foo foobar1() {return foo();}
const foo foobar2() {return foo();}

int main()
{
foobar1().barfoo();
foobar1().bar();
foobar2().barfoo();
foobar2().bar();
}
В последнем варианте ( foobar2().bar(); ) у вас  будет ошибка.
Записан
billygates
Гость
« Ответ #3 : Май 09, 2011, 11:13 »

2 Igors
Что-то я вашего примера не понял. Может ,конечно, праздники так действуют.
Аналогично. Вполне себе можно менять, как я только что проверил на примере
Код
C
#include <iostream>
#include <string>
 
class Foo
{
public:
 Foo()
  : bar_("somebar") {}
 
  const std::string bar() const { return bar_; }
 
private:
 const std::string bar_;
};
 
int main(int argc, char** argv)
{
   Foo foo;
   std::string bar = foo.bar();
   bar.append(".some.preffix");
 
   return 0;
}
 

Разница есть в таком случае:
Спасибо за пример, стало немного понятно. Однако пока это не отменяет для меня синтетичности такой возможности. Может, пожалуйста, кто-то нибудь привести пример из жизни (STL, Qt), когда такое действительно применяется и без этого не обойтись?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Май 09, 2011, 12:12 »

2 Igors
Что-то я вашего примера не понял. Может ,конечно, праздники так действуют.
Вы инициализируете константу. Все равно, что справа возвращается const или не const объект.  От этого вашему appPath не холодно, не  жарко.
Пример когда станет холодно
Код
C++ (Qt)
const string & Test( void )
{
 return string("abc");  // gcc пропустит (хотя и вякнет варнингом)
}
 
...
const string * test = &Test();  // и это пройдет
int array[100];  // содержимое (на что указывает test) перетерто
 
Записан
Sancho_s_rancho
Гость
« Ответ #5 : Май 09, 2011, 12:40 »

Только причем тут  возвращение константного объекта, о котором спрашивал billygates?
В последнем примере возвращается ссылка на временный объект. Возвратить можно ссылку или указатель (это одно и тоже) с const или без него. В любом случае код приведет к беде, т.к. объект уничтожен.
Записан
brankovic
Гость
« Ответ #6 : Май 09, 2011, 13:14 »

Разница есть в таком случае:
...
В последнем варианте ( foobar2().bar(); ) у вас  будет ошибка.

пример правильный, но в реальности такую конструкцию невозможно использовать по делу (не видел нормального применения ни разу). Когда в коде вижу

Код
C
const std::string get_name () const;
const long get_size () const;
...
 

то так оцениваю варианты:

1. с вероятностью .9 автор идиот
2. с вероятностью .09 автор недавно изучил слово const и ставит его везде, где можно
3. с вероятностью .009 в проекте идиотский coding standart
4. в случае сложных типов всегда остаётся шанс, что это и правда нужно.. лучше внимательно изучить этот кусок кода

в общем лучше так не делать никогда, чтобы читающему не пришлось ломать голову над вашими экзерцисами
Записан
ieroglif
Гость
« Ответ #7 : Май 09, 2011, 14:00 »

Код
class A
{
public:
   A();
   inline int inc()
   {
       i++;
       return i;
   }
   int i;
};
 
class B
{
public:
   B() {}
   inline const A * getA()
   {
       return &a;
   }
   A a;
};
 
B b;
b.a.inc();   //ok
b.getA()->inc(); //oblom
 
работает оно так:
const T * name; - это "на константную Т указатель". это значит что сама переменная name не константна, и в неё можно записать адрес другого объекта, но с объектом, который расположен по этому указателю надо обращаться как с константным, т.е. нельзя вызывать "не const" методы, способные повлиять на внутреннее состояние объекта.
T * const name; - это "константный указатель на T". соответсвенно сама переменная name константна и изменена быть не может, но объект на который она указыват - "динамичен" Улыбающийся

соответсвенно из этого уже и использование: если я хочу вернуть из метода что-то такое, что совсем не надо изменять - я обзову
const T Object::method(); и буду спокоен что всё ок Улыбающийся так что используется в проектировании классов Улыбающийся
Записан
brankovic
Гость
« Ответ #8 : Май 09, 2011, 14:10 »

так что используется в проектировании классов Улыбающийся

а ещё при проектировании классов полезно:

писать пустой конструктор, когда он не нужен (2 раза)
писать inline, который не нужен (2 раза)
возвращать const A* из неконстантного метода
приводить пример с const A *, когда вопрос был про A * const
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Май 09, 2011, 14:13 »

Только причем тут  возвращение константного объекта, о котором спрашивал billygates?
Отвечаю на то что спросили
? Ведь все равно возврат происходит по значению. Если бы по ссылке -- то было бы понятно.
Не всегда удается заменить на возврат константной ссылки.

Может, пожалуйста, кто-то нибудь привести пример из жизни (STL, Qt), когда такое действительно применяется и без этого не обойтись?
Ну обойтись можно без очень многого (и без const вообще), а когда это имеет смысл - найти примеры несложно

Код
C++ (Qt)
typedef std::map <int, int> TMap;
const TMap GetMap( void );    
 
// чтобы пресечь
GetMap()[i]...
 

Код
C++ (Qt)
#if MODE_PTR
typedef int * TInt;
#else
typedef MyStruct TInt;
#endif
 
const TInt GetInt( void );    
 
Записан
brankovic
Гость
« Ответ #10 : Май 09, 2011, 15:28 »

// чтобы пресечь
Код
C++ (Qt)
GetMap()[i]...
 

пришлось заодно присечь полезное GetMap ().swap (m); Кроме того, умный пользователь сделает Map m = GetMap (); и понаставит [] сколько захочет. Хороший пример дайте, где это естественно и от чего-то спасает.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Май 10, 2011, 08:04 »

Кроме того, умный пользователь сделает Map m = GetMap (); и понаставит [] сколько захочет. Хороший пример дайте, где это естественно и от чего-то спасает.
Да хотя бы так
Код
C++ (Qt)
const std::vector <int> GetVector( void );
// использование
const std::vector <int> vec = GetVector();
 
Надо понимать что автор хотел сказать - возвращаемый вектор должен использоваться "как есть", только по чтению. Конечно ф-ция могла возвращать и не константу, но это так в любом случае
Код
C++ (Qt)
const std::vector <int> & GetVector( void );
// использование
const std::vector <int> & vec = GetVector();
 
Не делаем же мы вывод что возвращать константную ссылку избыточно, т.к. мы ее можем всегда ее получить из неконстантной.

Эти 2 примера по существу идентичны, просто один широко известен, другой нет - отсюда и противоположная оценка Улыбающийся

Код
C
const long get_size () const;
...
 

то так оцениваю варианты:

1. с вероятностью .9 автор идиот
Меня например раздражает ".9" (вместо цивильного "0.9f") но это не основание обзывать человека идиотом Улыбающийся Писать "const long" я не стану, но и ничего плохого не вижу - дело вкуса.
Записан
Akon
Гость
« Ответ #12 : Май 10, 2011, 15:13 »

Привет,

Когда может потребовать такое:
Код
C
const std::string myMethod();
вместо
Код
C
std::string myMethod();
? Ведь все равно возврат происходит по значению. Если бы по ссылке -- то было бы понятно.

Спасибо.

Да просто пресекает никчемные конструкции, наподобие таких:
Код:
myMethod().clear();
или
parentWidget.findChildren<QPushButton *>().clear();
« Последнее редактирование: Май 10, 2011, 15:15 от Akon » Записан
Anchorite
Гость
« Ответ #13 : Май 12, 2011, 17:39 »

Это сделано затем, чтобы случайно не написать ахинею типа

Код:
Class.myMethod() = something.

А получть это можно просто допустив опечатку при записи оператора сравнения.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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