Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопрос по инкапсуляции 
:(
    Опции темы
INHazeR
Дата 4.11.2007, 21:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 8.12.2006

Репутация: нет
Всего: нет



Добрый день.
Предположим, имеем
Код

class Worker
{
public:
    Worker(char* _name) : name(_name) { }
    virtual ~Worker() {}
    const char* GetName() const { return name; }
protected:
    char* name;
    int salary;
}

Т.е.  инициализация поля класса, представляющего собой указатель на массив символов, происходит по указателю, данному пользователем. Я себе представляю это так:
Код

int main(int argc, char* argv[])
{
    Worker w = Worker("Good worker");
    return 0;
}

Теперь представим себе такую ситуацию:
Код

int main(int argc, char* argv[])
{
    char* myname = "Bad worker";
    Worker w = Worker(myname);
    cout << w.GetName() << endl;
    delete[] myname;
    cout << w.GetName() << endl;
    return 0;
}

Получается по смыслу полная чушь. Мы создали объект класса, инициализировали одно из его полей соответствующей переменной, расположенной по адресу myname. И вместе с тем, имеем неограниченный доступ фактически к частной переменной класса, name. Что и приводит вот к таким плачевным результатам.
Напрашивается решение: 
Код

    Worker(char* _name)
    {
        int size = strlen(_name);
        name = new char[size + 1];
        strcpy(name, _name);
        name[size] = 0;
    }

Однако это не работает. Даже если бы и работало, появляется вопрос: а что клиенту делать с указателем _name? Удалять вручную после создания объекта класса?
В общем, совсем я запутался. 
Прошу помощи и разъяснений, и пардон если вопрос глупый. smile
PM MAIL   Вверх
Daevaorn
Дата 4.11.2007, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Можно и нужно использовать std::string
PM MAIL WWW   Вверх
INHazeR
Дата 4.11.2007, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 8.12.2006

Репутация: нет
Всего: нет



Цитата(Daevaorn @  4.11.2007,  21:12 Найти цитируемый пост)
Можно и нужно использовать std::string 

это все здорово, но вопрос остается открытым... 

PM MAIL   Вверх
Daevaorn
Дата 4.11.2007, 21:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(INHazeR @  4.11.2007,  22:16 Найти цитируемый пост)
это все здорово, но вопрос остается открытым... 

это ответ на вопрос и есть. поле класса должно быть std::string. тогда нет проблем с владением,
PM MAIL WWW   Вверх
Alek86
Дата 4.11.2007, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



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

потому std::string и подходит идеально. он просто скопирует себу ту твою строку  будет хранить созданную копию у себя. а при удалении экземпляра класса Worker, std::string сам удалит копию.

Это сообщение отредактировал(а) Alek86 - 4.11.2007, 22:41


--------------------
user posted image    user posted image
PM MAIL   Вверх
Lazin
Дата 4.11.2007, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(INHazeR @  4.11.2007,  21:07 Найти цитируемый пост)
    
Код

Worker(char* _name)
    {
        int size = strlen(_name);
        name = new char[size + 1];
        strcpy(name, _name);
        name[size] = 0;
    }

Потом в деструкторе это нужно удалить. В большинстве случаев объект сам должен управлять временем жизни своих данных.
PM MAIL Skype GTalk   Вверх
Alek86
Дата 5.11.2007, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



жесть
зачем этому учить? smile

пусть лучше пользует уже std::string.

ЗЫ.
Код

Worker(const char* _name)


ЗЗЫ. Почти как рядом в топике у архимеда вышло  smile 

Это сообщение отредактировал(а) Alek86 - 5.11.2007, 19:23


--------------------
user posted image    user posted image
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0651 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.