Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Вопрос по инкапсуляции


Автор: INHazeR 4.11.2007, 21:07
Добрый день.
Предположим, имеем
Код

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

Автор: Daevaorn 4.11.2007, 21:12
Можно и нужно использовать std::string

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

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

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

это ответ на вопрос и есть. поле класса должно быть std::string. тогда нет проблем с владением,

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

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

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

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

Потом в деструкторе это нужно удалить. В большинстве случаев объект сам должен управлять временем жизни своих данных.

Автор: Alek86 5.11.2007, 19:23
жесть
зачем этому учить? smile

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

ЗЫ.
Код

Worker(const char* _name)


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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)