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

Какие ошибки допущены при проектировании класса - C++

Восстановить пароль Регистрация
 
 
trev
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
27.07.2014, 12:36     Какие ошибки допущены при проектировании класса #1
Подскажите пожалуйста, какие ошибки допущены при проектировании класса, если они имеются:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "stdafx.h"
#include <fstream>
 
class FileClient
{
protected:
    char* p;
public:
 
    virtual void connect() = 0;
    void close(){}
    virtual void ping()
    {
        printf("%s : %s", "__FUNCTION__", p);
    }
    FileClient()
    {
        p = new char[10];
        p[0] = '1';
    }
    ~FileClient()
    {
        delete p;
    }
};
class Client : public FileClient
{
    FILE* hFile;
public:
    virtual void connect()
    {
        hFile = fopen("d:\test.txt", "w");
    }
    void ping()
    {
        char arr[] = { 0, 0, 5, 56, 12, 32 };
        fwrite(arr, 1, sizeof(arr), hFile);
        FileClient::ping();
    }
    ~Client()
    {
        delete[] p;
        p = 0;
    }
};
 
int main()
{
    FileClient* client = new Client;
    client->connect();
    client->ping();
    delete client;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
zss
Модератор
Эксперт С++
 Аватар для zss
5942 / 5547 / 1783
Регистрация: 18.12.2011
Сообщений: 14,154
Завершенные тесты: 1
27.07.2014, 12:52     Какие ошибки допущены при проектировании класса #2
C++
1
2
3
4
5
6
7
8
9
10
FileClient()
    {
        p = new char[10];
        p[0] = '1';
        p[1]=0; // строка должна заканчиваться терминальным нулем
    }
    ~FileClient()
    {
        delete[]  p; // удаляется массив
    }
Добавлено через 2 минуты
C++
1
2
3
4
5
~Client()
    {
       ~FileClient();
    }
Client():FileClient(){}
trev
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
27.07.2014, 13:05  [ТС]     Какие ошибки допущены при проектировании класса #3
спасибо, но еще отказывается компилиться строка:
C++
1
    hFile = fopen("d:\test2.txt", "w");
#include <stdio.h> добавлено
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
27.07.2014, 13:30     Какие ошибки допущены при проектировании класса #4
trev, обратный слэш надо экранировать
C++
1
"d:\\test2.txt"
либо используй прямой
C++
1
"d:/test2.txt"
Добавлено через 9 минут
Цитата Сообщение от trev Посмотреть сообщение
#include <stdio.h> добавлено
C++
1
2
3
4
5
#include <cstdio>
 
// ...
 
hFile = std::fopen("d:/test2.txt", "w");
Добавлено через 2 минуты
+ файл не закрывается.
trev
 Аватар для trev
0 / 0 / 0
Регистрация: 10.07.2014
Сообщений: 13
27.07.2014, 13:54  [ТС]     Какие ошибки допущены при проектировании класса #5
так.. вроде все работает, но почему то этот фрагмент:
C++
1
2
3
4
5
6
void ping()
    {
        char arr[] = { '0', '0', '5', '56', '12', '32' };
        fwrite(arr, 1, sizeof(arr), hFile);
        FileClient::ping();
    }
не выводит двузначные символы как надо, например вместо "56" он записывает в файл 6, "12" = "2" и так далее..
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
27.07.2014, 14:32     Какие ошибки допущены при проектировании класса #6
trev, char хранит один символ, 56 - это два символа.
DrOffset
6418 / 3792 / 876
Регистрация: 30.01.2014
Сообщений: 6,579
27.07.2014, 14:47     Какие ошибки допущены при проектировании класса #7
trev, потому что multi-character character constant имеет тип int, а не char. Лучше так вообще не делать. Ибо непереносимо, и даже здесь (в таком простейшем случае) проявляются всякие побочные эффекты.

Добавлено через 28 секунд
Цитата Сообщение от gray_fox Посмотреть сообщение
вообще запись вроде '56' некорректна
Корректна, но непереносима. Это multi-character character constant.

Добавлено через 10 минут
Цитата Сообщение от trev Посмотреть сообщение
не выводит двузначные символы как надо, например вместо "56" он записывает в файл 6, "12" = "2" и так далее..
Внутреннее устройство multi-character character constant может отличаться от компилятора к компилятору. Но здесь, видимо, происходит следующее:
C++
1
2
3
4
5
6
7
8
9
int main()
{
    int b = '12';
// запись мультисимвола '12' в little-endian
//    *((char*)&b)       = '2';
//    *(((char*)&b) + 1) = '1';
 
    char c = (char)b; //получаем 2
}
Добавлено через 3 минуты
trev, вот тут еще почитай.
-=ЮрА=-
Заблокирован
Автор FAQ
27.07.2014, 14:52     Какие ошибки допущены при проектировании класса #8
Цитата Сообщение от trev Посмотреть сообщение
FILE* hFile;
- почему не обнуляем?
Цитата Сообщение от trev Посмотреть сообщение
~Client()
* * {
* * * * delete[] p;
* * * * p = 0;
* * }
- почему не закрываем возможно открытый файловый поток?
Цитата Сообщение от trev Посмотреть сообщение
hFile = fopen("d:\test2.txt", "w");
- если в проекте в настрйоках юникод то
C++
1
hFile = fopen(L"D:\\test2.txt", L"w");
если проект без юникода, то hFile = fopen("D:\\test2.txt", "w");
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <fstream>
#include <cstdio>
using namespace std;
 
class FileClient
{
protected:
    char* p;
public:
 
    virtual void connect() = 0;
    void close(){}
    virtual void ping()
    {
        printf("%s : %s", "__FUNCTION__", p);
    }
    FileClient()
    {
        p = new char[10];
        p[0] = '1';
    }
    ~FileClient()
    {
        delete p;
    }
};
class Client : public FileClient
{
    FILE* hFile;
public:
    Client() : hFile( NULL ) {}//кто обнулять будет?
    virtual void connect(){
        //глупая функция путь к файлу и параметры следует передават ьв функцию а не забивать
        hFile = fopen("D:\\test.txt", "w");
    }
    void ping()
    {
        char arr[] = { 0, 0, 5, 56, 12, 32 };
        fwrite(arr, 1, sizeof(arr), hFile);
        FileClient::ping();
    }
    ~Client()
    {
        if( p )
        delete[] p;
        p = 0;
        if( hFile )
            fclose(hFile);
    }
};
 
int main()
{
    FileClient* client = new Client;
    client->connect();
    client->ping();
    delete client;
}
http://codepad.org/HWxjYvDk
Самой большой глупостью считаю использование потока из stdio к чему вообще fstream?
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
27.07.2014, 14:55     Какие ошибки допущены при проектировании класса #9
Кстати, деструктор то в FileClient должен быть виртуальным.
DrOffset
6418 / 3792 / 876
Регистрация: 30.01.2014
Сообщений: 6,579
27.07.2014, 15:04     Какие ошибки допущены при проектировании класса #10
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
if( p ) delete[] p;
На ноль не нужно проверять перед delete. Для delete гарантировано стандартом корректное поведение при передаче ему нуля.
-=ЮрА=-
Заблокирован
Автор FAQ
27.07.2014, 15:09     Какие ошибки допущены при проектировании класса #11
Цитата Сообщение от DrOffset Посмотреть сообщение
На ноль не нужно проверять перед delete. Для delete гарантировано стандартом корректное поведение при передаче ему нуля.
- а если передали битый поинтер + ещё линкер с отклонением от стандарта (скажем студийный, который сгененрирует исключение)?
DrOffset
6418 / 3792 / 876
Регистрация: 30.01.2014
Сообщений: 6,579
27.07.2014, 15:14     Какие ошибки допущены при проектировании класса #12
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
а если передали битый поинтер + ещё линкер с отклонением от стандарта
Как проверка на ноль может вычислить битый пойнтер? И при чем тут линкер?
Вот этой проверкой:
C++
1
2
if(p)
   delete [] p;
ты ничего кроме нуля в p не отдетектишь, однако стандартом гарантируется что вот такая запись корректна
C++
1
2
p = 0;
delete[] p;
(и я не встречал ни одно компилятора на 5 платформах, с которыми я работаю, который вел бы себя иначе).
Пора уже развеивать мифы.
-=ЮрА=-
Заблокирован
Автор FAQ
27.07.2014, 15:24     Какие ошибки допущены при проектировании класса #13
Цитата Сообщение от DrOffset Посмотреть сообщение
Пора уже развеивать мифы.
- битый поинтер
http://codepad.org/cQqjuIKm
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
27.07.2014, 15:26     Какие ошибки допущены при проектировании класса #14
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
- битый поинтер
http://codepad.org/cQqjuIKm
И как тут поможет if (ptr) ?
Voivoid
 Аватар для Voivoid
580 / 256 / 12
Регистрация: 31.03.2013
Сообщений: 1,283
27.07.2014, 15:27     Какие ошибки допущены при проектировании класса #15


Advanced C++ такой advanced
DrOffset
6418 / 3792 / 876
Регистрация: 30.01.2014
Сообщений: 6,579
27.07.2014, 15:27     Какие ошибки допущены при проектировании класса #16
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
битый поинтер
Действительно. Неужели правда нужно это объяснять?
Цитата Сообщение от gray_fox Посмотреть сообщение
И как тут поможет if (ptr) ?
-=ЮрА=-
Заблокирован
Автор FAQ
27.07.2014, 15:54     Какие ошибки допущены при проектировании класса #17
DrOffset, по моему ты сейчас кивнул в мою сторону.
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
29
30
31
32
33
34
35
36
37
38
#include <iostream>
using namespace std;
 
class cObj{
    static int param;
public:
    cObj(){
        param++;
    }
    ~cObj(){
        param--;
    }
    static int GetParam(){
        return param;
    }
    static void Reset(){
        param = 0;
    }
};
 
int cObj::param = 0;
 
void operator delete(void *p)
{
    int param = cObj::GetParam();
    if( param )
        throw param;
}
 
int main(){
    cObj * ptr = new cObj[5];
    ptr = 0;
    if( ptr )
        delete [] ptr;
    else
        cObj::Reset();
    return 0;
}
Фильтровать поинтер нужно всегда, конечно если тут люд кроме консоли нечего не видиывал то понятно, или никогда не перегружал ряд операторов, чтобы отладить какой нибудь нетривиальный проект.
Первый макрос MFC
C++
1
2
3
4
5
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
Добавлено через 4 минуты

Не по теме:

Цитата Сообщение от gray_fox Посмотреть сообщение
И как тут поможет if (ptr) ?
- представь если у тебя несколько дочерних управляемых процессов, которые застрянут если просто так закроешь родительский.

gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
27.07.2014, 15:58     Какие ошибки допущены при проектировании класса #18
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
- представь если у тебя несколько дочерних управляемых процессов, которые застрянуть если просто так закроешь родительский.
Иии... как это связано с оператором delete?
-=ЮрА=-
27.07.2014, 16:00
  #19

Не по теме:

Цитата Сообщение от gray_fox Посмотреть сообщение
Иии... как это связано с оператором delete?
- раскрой глаза

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.07.2014, 16:01     Какие ошибки допущены при проектировании класса
Еще ссылки по теме:

Какие тут ошибки C++
C++ Использование конструкторов и деструктора при проектировании пользовательского класса

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

Или воспользуйтесь поиском по форуму:
Voivoid
 Аватар для Voivoid
580 / 256 / 12
Регистрация: 31.03.2013
Сообщений: 1,283
27.07.2014, 16:01     Какие ошибки допущены при проектировании класса #20
Цитата Сообщение от DrOffset Посмотреть сообщение
И как тут поможет if (ptr) ?
Подозреваю, что это что-то из разряда:
Цитата Сообщение от -=ЮрА=-
Некоторые вещи я предпочитаю знать лишь один
Yandex
Объявления
27.07.2014, 16:01     Какие ошибки допущены при проектировании класса
Ответ Создать тему
Опции темы

Текущее время: 13:46. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru