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

Выпиливание экземпляра класса самим собой - C++

Восстановить пароль Регистрация
 
 
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
11.10.2012, 16:52     Выпиливание экземпляра класса самим собой #1
Наслышан и начитан о плохом тоне и ub команды delete this, однако, будет ли ошибкой вызывать вместо delete this деструктор?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class SECURITY
{
*some data*
public :
SECURITY()
{
*check something, and it is wrong*
~SECURITY();
*ну а здесь уже нет никаких обращений к полям класса или функциям, работающими с полями*
}
~SECURITY()
{
delete *somedata*;
delete [] *somedata*;
...
}
}
};
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.10.2012, 16:52     Выпиливание экземпляра класса самим собой
Посмотрите здесь:

C++ Сложение экземпляра базового класса и экземпляра наследника
C++ Вызов метода класса без создания экземпляра класса.
создание экземпляра класса C++
C++ Как построить экземпляр дочернего класса на основе готового экземпляра базового класса?
C++ Создание нового экземпляра дочернего класса из экземпляра базового
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
11.10.2012, 17:58     Выпиливание экземпляра класса самим собой #2
Не надо изобретать велосипед. Для неустранимых ошибок в конструкторе пользуются исключениями (см. throw и заголовок <stdexcept>). Если в теле конструктора выбрасывается исключение, то деструктор всех членов будет вызван автоматически, и надо позаботиться только о том, чтобы подчистить то, что наворочено уже непосредственно в самом теле.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdexcept>
#include <vector>
class Spoiled {
public:
    Spoiled(int data1, int data2);
    ~Spoiled();
private:
    std::vector<int> d;
};
 
Spoiled::Spoiled(int data1, int data2)
{
    if(data1 > data2)
        throw std::invalid_argument("Создание Spoiled: data1 не должен превышать data2");
   d.assign(data2, data1);
}
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
11.10.2012, 18:17  [ТС]     Выпиливание экземпляра класса самим собой #3
Nick Alte, я думал, что сделать это exception'ом, но вышло так, что, если я из конструктора выбрасываю тип int, который за'define'ен, то в main у меня не перехватывается exception, а сразу идет ошибка приложения с критическим завершением. Т.е :
C++
1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
try
{
SECURITY *s = new SECURITY;
}
catch (...)
{
printf("Where is an exception!\n");
}
return 0;
}
вызовет конструктор, в котором throw(10) (допустим), и умрет, без printf'а
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
11.10.2012, 18:28     Выпиливание экземпляра класса самим собой #4
nexen, пример с define можете представить? Без него все ловится.
http://liveworkspace.org/code/f454fd...69ed1bfe9c3dd8
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
11.10.2012, 18:51  [ТС]     Выпиливание экземпляра класса самим собой #5
soon, ничего существенного. Вид :
C++
1
2
3
4
5
6
7
8
try
    {
        verifyUser = new SECURITY;
    }
    catch(...)
    {
printf("dwada\n");
    }
где в конструкторе :
C++
1
2
3
4
SECURITY::SECURITY()
{
throw(SUCCESS);
}
, где
C++
1
#define SUCCESS 0
Подобная конструкция выкидывает критическую ошибку, мол, пойман эксепшен, но ошибка ловится дебагером, а не catch. В релизе просто выкидывает из приложения.
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
11.10.2012, 19:11     Выпиливание экземпляра класса самим собой #6
Имхо, проблема в компиляторе.
http://liveworkspace.org/code/8da562...a152a2a1adf093
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
11.10.2012, 19:13     Выпиливание экземпляра класса самим собой #7
Вызывать деструктор в конструкторе? Оригинально.)))
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
11.10.2012, 19:14  [ТС]     Выпиливание экземпляра класса самим собой #8
soon, и что тогда делать? ;( Только деструктором в конструкторе?
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
11.10.2012, 19:18     Выпиливание экземпляра класса самим собой #9
Цитата Сообщение от nexen Посмотреть сообщение
Только деструктором в конструкторе?
НЕЕЕЕЕЕЕЕЕТ! Это не то, чтобы UB, это вообще пипец.
Попробуй явно тип исключения указывать: throw int(-1);

Добавлено через 1 минуту
Или
#define SUCCESS int(0)

Хотя я бы не называл код ошибки словом SUCCESS.)
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
11.10.2012, 19:23  [ТС]     Выпиливание экземпляра класса самим собой #10
Deviaphan, перезапустил VS и всё заработало /facepalm..
Вопрос такой, если я прерываю конструктор, то delete делать не нужно? А что если до throw в конструкторе, я уже выделил память для строк char *lol = new char[1000];. Будут ли они подчищены?
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
11.10.2012, 19:29     Выпиливание экземпляра класса самим собой #11
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
class A
{
public:
A()
: arr(0)
{
    try
    {
        arr = int[1000];
        ...
    }
    catch(...)
    {
        Destruct();
    }
}
~A()
{
    Destruct();
}
 
private:
   void Destruct()
   {
      delete[] arr;
      ...
   }
int * arr;
...
};
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
11.10.2012, 19:30     Выпиливание экземпляра класса самим собой #12
nexen, для этого используйте smart pointers. Чтобы не заморачиваться
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.10.2012, 16:53  [ТС]     Выпиливание экземпляра класса самим собой #13
Да чтоб его! Спустя некоторое время опять throw выбрасывает из программы полностью (пишет, что access violation reading, сразу после throw). Вид конструктора :
C++
1
2
3
4
5
6
FILE *usersData = fopen("users.dat", "rb");
    if (usersData == NULL)
    {
        printf(Rus("Ошибка : не существует файла пользователей.\n"));
        throw(PROCESS_FAILURE);
    }
Вид перехвата :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
try
    {
        verifyUser = new _SECURITY;
    }
    catch(...) // пробовал и catch(BOOL exception) / catch(const BOOL exception)
    {
        //if (exception == PROCESS_FAILURE)
        {
            printf(Rus("Ошибка : инициализации службы безопастности прервана.\nПриложение будет закрыто.\n"));
            _getch();
            return 0;
        }
    }
C++
1
#define PROCESS_FAILURE 1
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
13.10.2012, 16:57     Выпиливание экземпляра класса самим собой #14
А зачем ты пишешь throw(PROCESS_FAILURE); а не просто throw PROCESS_FAILURE; ?
На ошибку это никак не влияет, но просто интересно.
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
13.10.2012, 17:09     Выпиливание экземпляра класса самим собой #15
nexen, помнится, в прошлый раз вам помог перезапуск.
Почему бы не использовать что-то вроде этого? Я больше в плане читабельности, не знаю, как себя поведет MSVC
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
#include <iostream>
#include <stdexcept>
#include <memory>
 
class File_does_not_exists: public std::exception
{
    std::string _what;
 
public:
    explicit File_does_not_exists(const std::string& what_arg): _what(what_arg)
    {
 
    }
 
    explicit File_does_not_exists(const char* what_arg): _what(what_arg)
    {
 
    }
 
    const char* what() const noexcept
    {
        return _what.c_str();
    }
};
 
struct Foo
{
    Foo()
    {
        throw File_does_not_exists("some file");
    }
};
 
int main()
{
    try
    {
        std::shared_ptr<Foo> f_ptr(new Foo());
    }
    catch(const std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
    return 0;
}
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
13.10.2012, 17:21     Выпиливание экземпляра класса самим собой #16
soon, зачем дублировать то, что и так уже есть в std::exception?
C++
1
2
3
4
5
6
7
#include <stdexcept>
#include <string>
 
class file_does_not_exist: public std::runtime_error {
public:
    file_does_not_exist(const std::string& msg): std::runtime_error(msg) {}
};
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.10.2012, 20:33  [ТС]     Выпиливание экземпляра класса самим собой #17
Deviaphan, везде, где читал, была конструкция throw(). Даже и не знал, что throw .. возможно. Спасибо. Хотя я все равно буду писать throw(), ибо привычнее.


soon, в этот раз не помог, да и не дело это - решать проблему перезапусками.
К сожалению, наследоваться от exception'ов нельзя (по условию). Нужна конструкция, получающая int или catch(...), где int за'define'нен под ошибки.

Проблема решена: ) Всё дело было в переполнении буферной переменной

Добавлено через 22 минуты
Throw нельзя делать в case?..
C++
1
2
3
4
5
6
7
switch (flag)
        {
        case 'н':
            throw PROCESS_FAILURE; // не воспринимает
 
        case 'д':
            break;
а
C++
1
2
if (flag == 'н')
throw PROCESS_FAILURE;
работает
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
14.10.2012, 06:55     Выпиливание экземпляра класса самим собой #18
throw можно делать везде, кроме деструктора. В деструкторе тоже можно, но не нужно.
У тебя опять что-то глючит. Перезапусти студию и сделай полный ребилд проекта.
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
14.10.2012, 07:46  [ТС]     Выпиливание экземпляра класса самим собой #19
Deviaphan, не помогло ;<

Добавлено через 20 минут
А вообще могу ли я прерывать конструктор? Допустим, в конце конструктора (последней строчкой) вызвать его метод типа Dialog() и работать в нем и с экземпляром, и вообще. Будет ли в этом что-то плохое?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.10.2012, 08:01     Выпиливание экземпляра класса самим собой
Еще ссылки по теме:

C++ Создание экземпляра класса до определения класса
Передача свойства одного экземпляра класса другому экземпляру класса C++
C++ Видимость экземпляра класса внутри класса

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

Или воспользуйтесь поиском по форуму:
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
14.10.2012, 08:01     Выпиливание экземпляра класса самим собой #20
Бросать исключения в конструкторе можно и нужно. "последней строчкой" работать с этим объектом (вызывать методы и т.п.) можно только в том случае, если ты перехватил исключение внутри конструктора и корректно их обработал. Т.е. если после отработки исключения у тебя получился корректно сформированный экземпляр. В противном случае ты будешь вызывать методы для не сформированного объекта, это почти то же самое, что сделать приведение типа случайного адреса к указателю на класс и что-то там вызывать. Ну и виртуальные функции в конструкторе вызывать нельзя даже при отсутствии исключений.

Добавлено через 1 минуту
Цитата Сообщение от nexen Посмотреть сообщение
не помогло ;<
Попробуй
C++
1
2
       case 'н':
            { throw PROCESS_FAILURE; } // не воспринимает
При генерации исключения ты создаёшь новый объект, а case нельзя новые объекты создавать. Только если вложенную область сделать.
Yandex
Объявления
14.10.2012, 08:01     Выпиливание экземпляра класса самим собой
Ответ Создать тему
Опции темы

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