Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 56, средняя оценка - 4.66
Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
#1

Константные функции-члены класса, возвращающие ссылку на константу - C++

08.08.2011, 21:09. Просмотров 7317. Ответов 64
Метки нет (Все метки)

Упражняюсь по книге Липпмана, выполняю задания по теме классы.
Необходимо реализовать класс person, который способен хранить имя и адрес человека, а также создать функции, возвращающие при обращении имя и адрес.
Вопрос, который ставит автор книги: "Должны ли эти функции быть константными? Объясните почему."
Вот тут я начал путаться. Вот моя реализация:
файл person.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#ifndef PERSON_H_
#define PERSON_H_
 
class person {
public:
    //конструктор, принимающий две строки типа string
    person( std::string &_name, std::string &_addres ) :
        name( _name ), addres( _addres ) {
    }
    //метод, возвращающий addres
    const std::string &get_addres() const {
        return addres;
    }
    //метод, возвращающий name
    const std::string &get_name() const {
        return name;
    }
 
private:
    //поле для хранения имени
    std::string name;
    //поле для хранения адреса
    std::string addres;
};
 
#endif /* PERSON_H_ */
Для тестирования класса, файл test_class_person.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include "person.h"
using namespace std;
 
int main() {
    string str1 = "Alexander";
    string str2 = "Zelenogradsk";
    person pers( str1, str2 );
    cout << pers.get_name() << " " << pers.get_addres() << endl;
    
    string str3 = pers.get_name();
    str3 += "222";
    cout << str3 << " " << pers.get_name();
    return 0;
}
Я решил так
1) Константными эти функции должны быть, так как они не меняют значений переменных-членов объекта.
2) Возвращать они должны лишь константную ссылку на строку, а не просто тип string, дабы избежать ненужного копирования.
Прав ли я? Если нет, то объясните почему.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.08.2011, 21:09
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Константные функции-члены класса, возвращающие ссылку на константу (C++):

Константные функции-члены ? - C++
Для чего использовать #define ? не имеют права изменять поля класса почему ? class Array { ... inline double operator...

Константные функции-члены - C++
можно ли функцию-член объявить константной, если она возвращает указатель-член класса? Ведь она не изменяет занчение самого укзателя, но...

класс «Строка» (данные-члены класса – строчка, функции-члены класса – операции) - C++
Помогите пожалйуста с реализацией программы... Реализовать класс «Строка» (данные-члены класса – строчка (указатель на массив, ...

Почему нехорошо себя ведёт конструктор класса (не компилится ничё), если ему параметром ссылку на константу? - C++
То есть вообще непонятно ничё, вот, смотрите, этот пример не компилится: #include &lt;stdio.h&gt; class fee { public: //Не компилится ...

Массив указателей на функции-члены класса - C++
Задача заключается в том, что в private надо создать статическую переменную символьного типа, в protected просто переменные вещественного...

Использование указателей на функции-члены внутри самого класса - C++
День добрый форум! Возник такой вопрос. В классе А есть 3 функции и массив, в котором хранятся адреса этих функций. class A ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
CyBOSSeR
Эксперт C++
2300 / 1670 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
10.08.2011, 10:30 #31
Цитата Сообщение от Deviaphan Посмотреть сообщение
Но я предпочитаю возвращать константную ссылку для сложных объектов
В таких случаях умные указатели предпочтительнее, возвращать ссылки - слишком потенциально опасное действие, чтобы его производить.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1286 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.08.2011, 10:40 #32
умные указатели предпочтительнее
Абсолютно да!
Но чтобы возвращать умные указатели на внутренние данные объекта, эти данные должны быть умными указателями. Что не всегда желательно и возможно.
С другой стороны, С++ вообще очень потенциально опасный язык и речь должна идти о культуре программирования и опыте программиста. Когда пишешь простой и понятный код, опасные конструкции встречаются гораздо реже.
Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
10.08.2011, 15:22  [ТС] #33
Спасибо всем ответившим. На свой вопрос получил однозначный ответ.
easybudda
Модератор
Эксперт CЭксперт С++
9530 / 5523 / 932
Регистрация: 25.07.2009
Сообщений: 10,608
10.08.2011, 15:42 #34
Roof, ну и в заключении поясню суть своего примера: я его дома на ноуте с debian делал, там, напомню, два раза Vasya вывелось. А вот, как этот же самый код (отсюда скопировал) с другими компиляторами работает:
Константные функции-члены класса, возвращающие ссылку на константу
Константные функции-члены класса, возвращающие ссылку на константу
Можно долго гадать, или разбираться, почему оно так, но лучше просто не оставлять такие вещи на откуп компилятору...
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1286 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.08.2011, 15:50 #35
Цитата Сообщение от easybudda Посмотреть сообщение
почему оно так
Второй раз не Вася вывелся, а Вас(стрелочка).
lavan
52 / 52 / 1
Регистрация: 21.03.2009
Сообщений: 371
10.08.2011, 16:03 #36
Возврат const string & необходим чтобы избежать возможности изменять private часть класса без использования интерфейса
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<iostream>
#include<string>
using namespace std;
class A {
private:
string str;
public:
    A();
    string & fun();
    void show(){
     cout<<str;
    }
};
int main() {
  A obj;
  obj.show();
  obj.fun()="kol";//изменили str
  cout<<endl;
  obj.show();
  cin.get();
  return 0;
}
A::A(){
str="gflj";
}
string & A::fun(){
return str;
}
easybudda
Модератор
Эксперт CЭксперт С++
9530 / 5523 / 932
Регистрация: 25.07.2009
Сообщений: 10,608
10.08.2011, 16:04 #37
Цитата Сообщение от Deviaphan Посмотреть сообщение
Второй раз не Вася вывелся, а Вас(стрелочка).
Да, я заметил. В cygwin указатель указывает на буфер строки, которая к моменту второго обращения уже не существует. Мелкомягкий каким-то чудом сохраняет указатель, хоть она к тому времени и поменялась (на сколько знаю, оператор = должен бы уничтожать старую строку и создавать новую), а вот в BSD снова два Васи и без стрелок:
Константные функции-члены класса, возвращающие ссылку на константу
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1286 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.08.2011, 16:08 #38
Цитата Сообщение от easybudda Посмотреть сообщение
Мелкомягкий каким-то чудом сохраняет указатель
Не исключено, что была создана копия строки, в целях оптимизации. Насколько я помню, короткие строки хранятся в массиве в самом объекте, без выделения памяти. А раз обещался const компилятор мог создать копию. Поэтому изменив оригинальный объект осталась строка в копии... А вообще, чего гадать на ошибках, лучше так не писать и усё.)
easybudda
Модератор
Эксперт CЭксперт С++
9530 / 5523 / 932
Регистрация: 25.07.2009
Сообщений: 10,608
10.08.2011, 16:25 #39
Цитата Сообщение от Deviaphan Посмотреть сообщение
Поэтому изменив оригинальный объект осталась строка в копии...
Так в том и прикол, что мелкомягкий не создавал копии, просто вернул указатель на массив char* от строки-члена класса, который сохранился после присвоения строке другого значения, скорее всего по причине
Цитата Сообщение от Deviaphan Посмотреть сообщение
короткие строки хранятся в массиве в самом объекте, без выделения памяти
А вот про это
Цитата Сообщение от Deviaphan Посмотреть сообщение
лучше так не писать
я собственно и говорил.

Цитата Сообщение от lavan Посмотреть сообщение
Возврат const string & необходим чтобы избежать возможности изменять private часть класса без использования интерфейса
Спасибо, Кэп, разобрались уже...
Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
10.08.2011, 17:56  [ТС] #40
2 easybudda - я все примеры тестирую на Ubuntu с g++ и Ваш пример у меня вывел два раза Vasya, как и у Вас на Debain и BSD.

Цитата Сообщение от easybudda Посмотреть сообщение
Можно долго гадать, или разбираться, почему оно так, но лучше просто не оставлять такие вещи на откуп компилятору...
- с этим полностью согласен.
CyBOSSeR
Эксперт C++
2300 / 1670 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
10.08.2011, 18:07 #41
Цитата Сообщение от lavan Посмотреть сообщение
Возврат const string & необходим чтобы избежать возможности изменять private часть класса без использования интерфейса
Это неверно, от const_cast никак в таком случае не застраховаться.
LosAngeles
Заблокирован
10.08.2011, 19:44 #42
const_cast малость не подходит под категорию "случайное изменение инкапсулированных данных", всё по делу
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1286 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.08.2011, 19:48 #43
Цитата Сообщение от LosAngeles Посмотреть сообщение
const_cast малость не подходит под категорию "случайное изменение инкапсулированных данных"
Только вот некоторые бездари используют приведение типа в стиле Си, которому на всё ***.
CyBOSSeR
Эксперт C++
2300 / 1670 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
10.08.2011, 21:14 #44
Цитата Сообщение от LosAngeles Посмотреть сообщение
const_cast малость не подходит под категорию "случайное изменение инкапсулированных данных"
Где здесь фраза "случайное изменение инкапсулированных данных":
Цитата Сообщение от lavan Посмотреть сообщение
Возврат const string & необходим чтобы избежать возможности изменять private часть класса без использования интерфейса
?
Сыроежка
Заблокирован
10.08.2011, 21:30 #45
Цитата Сообщение от CyBOSSeR Посмотреть сообщение
Где здесь фраза "случайное изменение инкапсулированных данных":

?
Потому что если вы умышленно меняете то, что не предназначалось для изменения, как вы предложили с помощью const_cast, то вы - вредитель. Автор того сообщения имел в виду, когда можно неумышленно изменить то, что не подлежит изменению в виду неудачного интерфейса. То есть интерфейс должен способствовать правильному использованию данных и препятствовать их неправильному использованию. Это и было сказано в исходном сообщении. На мой взгляд, это совершенно ясно, так что не надо переспрашивать, "где зедсь фраза".
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.08.2011, 21:30
Привет! Вот еще темы с ответами:

Константные указатели и указатели на константу - C++
Чем они, собственно говоря, отличаются? Поясните, пожалуйста. Не знаю, как так получилось, что в разных источниках - разные...

В каких случаях компилятор делает функции-члены класса встроенными (inline)? - C++
Добрый день! Хочу спросить следующее: в интернете пишут, что если делать реализацию методов класса внутри его объявления, то такие методы...

Константные поля класса - C++
Такой вопрос, как инициализировать константные поля класса? Работают конструкции вида obj():t(0){}; который используется в примере ниже. А...

Константные статические объекты класса. - C++
Здравствуйте. Есть класс &quot;матрица&quot; нужно задать константные матрицы такие как E - единичная матрица и т.д., как это сделать? #include...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
10.08.2011, 21:30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru