2013-04-11 4 views
0

Первое, что я действительно не хотел публиковать на этом обмене кода стека, потому что это действительно небольшой объем кода, написанный примерно за 5 минут.Написание классов - хорошая практика

Я хочу спросить вас, допустим ли класс (мой первый в C++), который я написал. У меня на самом деле не было много кода C++, поэтому я не могу сравнивать это ни с чем.

Но я видел некоторые классы, реализующие только объявления функций, внутренняя часть этих функций была написана где-то еще в коде.

Я прошу вас о любых предложениях, если что-то не так. И почему они делают, как я описал в параграфе выше? Какой стиль кодирования лучше?

class File { 

private: 

    FILE *_handler; 
    char *_path; 
    long _size; 

    void setHandler(char *mode) 
    { 
     this->_handler = fopen(this->_path, mode); 
    } 

public: 

    File(char *path) 
    { 
     this->_path = path; 
    } 

    size_t read() 
    { 
     this->setHandler("r"); 
     char *buffer = (char*) malloc(sizeof(char)*this->_size); 

     return fread(buffer, 1, this->_size, this->_handler); 
    } 

    void write(char *data) 
    { 
     this->setHandler("w"); 
     fputs(data, this->_handler); 
    } 

    long size() 
    { 
     if(! sizeof(this->_size) > 0) 
     { 
      fseek(this->_handler, 0, SEEK_END); 
      this->_size = ftell(this->_handler); 
      rewind(this->_handler); 
     } 

     return this->_size; 
    } 

}; // End File 
+4

Попробуйте его на codeReview: http://codereview.stackexchange.com/?as=1 – Sam

+0

* «И почему они делают, как я описал в параграфе выше?» * Что вы имеете в виду, это разделение интерфейса и реализация. См. Здесь, почему это хорошая идея: http://stackoverflow.com/questions/333889/in-c-why-have-header-files-and-cpp-files – JBentley

+1

Один комментарий у меня есть, не так много о классе дизайн, заключается в том, что вы смешиваете код C с кодом C++. Такие вещи, как 'char *', 'fread',' fputs' и т. Д., Должны быть заменены их эквивалентами на C++. – JBentley

ответ

7

Здесь есть технические проблемы и то, что я рассматриваю как фундаментальные проблемы с дизайном.

технический:

Сколько раз вы открыть файл? Сколько раз вы его закрываете? Посмотрите, что делают read() и write().

Где находится обработка ошибок? Что произойдет, если fopen() не удастся. Никогда не используйте возвращаемые значения, не проверяя их.

Фундаментальные проблемы проектирования:

Вы выделяете память, которая освобождает его? Как правило, это плохая идея отделить ответственность за выделение и освобождение. Люди C++, как правило, используют умные указатели, чтобы помочь с этим.

Что сделал бы ваш код при наличии действительно большого файла?

Самый фундаментальный из всех: ваш интерфейс - это «вы должны помнить об этом» интерфейсе. Что произойдет, если кто-то называет read(), не задумываясь сначала вызвать size()? Почему ваш вызывающий абонент должен это делать? Создайте свой интерфейс с целью сделать жизнь вашего звонящего простым.

+0

Не могу поверить, что вы заметили все это и не заметили, что (A) 'size' не работает, если сначала не было вызвано' read' или 'write', и (B)' read' не дает вызывающий объект, который был прочитан, только возвращаемое значение (C). Файл никогда не закрывается. –

+0

Мне приходится открывать файл много раз, потому что каждый раз я открываю его в другом режиме. – user2252786

+0

Возможно, вам придется много раз открывать файл, но вы должны его снова закрыть или у вас не будет файлов. Вопрос моего вопроса в том, что у вас есть другое количество открытий и закрытий. (Mooing, мой первый технический момент охватывает отсутствие близких - хороший улов на других.) – djna

3

Там нет необходимости использовать this, если нет никакой двусмысленности.

File(char *path) 
{ 
    _path = path; 
} 

То же самое с функциями вы можете оставить this

size_t read() 
{ 
    setHandler("r"); 
    char *buffer = (char*) malloc(sizeof(char)*_size); 

    return fread(buffer, 1, _size, _handler); 
} 

Исполнительные функции в объявлении класса имеет его использования, но это не является обязательным (если с помощью шаблонов), вы можете определить свои функции в качестве источника файл и включите в него заголовочный файл класса. Это сохраняет реализацию класса отдельно от интерфейса класса.

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

Поскольку вы используете C++, вам может понадобиться изучить объекты файла C++ (fstream, ifstream, ofstream и т. Д.).

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

+1

Вам не нужно использовать 'this', но это делает ваш код более четким, потому что, когда кто-то читает код, он может сразу сказать, что этот объект является членом класса. Я основал его, чтобы быть полезным в прошлом, когда я читаю чужой код. – Caesar

+1

Я не вижу, как в этом случае «это» делает что-то ясно, это просто добавляет шум. Добавление 'this' перед каждым членом не будет делать функции более ясными, способ сделать функции и код ясными - иметь четко определенные имена и короткие функции, которые делают только одно. И если вы префикс своих членов '_', вам почти никогда не нужно' this' –

+2

@caesar Если код хорошо разработан (короткие, хорошо ограниченные функции, самодокументированные имена символов, разреженное использование глобальных символов), то это должно быть очевидно из контекста, является ли переменная членом или нет, что делает это «лишним». – JBentley