Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.12.2010, 18:53   #1
teapot
Пользователь
 
Регистрация: 04.12.2010
Сообщений: 23
Восклицание Как прервать работу конструктора объекта?

Вопрос, наверное, глупый)
Нужно создать объект с помощью конструктора, в качестве параметра передаётся строка, затем в теле самого конструктора её нужно преобразовать в число. Это обязательное условие.

Проблема в том, что если строку нельзя преобразовать в число, объёкт всё равно создастся, его можно будет просматривать и далее с ним работать. Разумеется, с некорректными данными. Можно ли как-то прервать создание объекта из конструктора, чтобы потом нельзя было к нему обратиться?

Думала о том, чтобы проверять строку на правильность до того, как запускать конструктор. Но это, наверное, некорректно. Потому что тогда каждому, кто когда-либо захочет использовать мой класс (теоретически), придётся ещё раз писать этот код.

Знающие люди, подскажите, как поступить, пожалуйста) Вот код конструктора.

Код:
TFrac::TFrac(char *str)
 {
    int len;
    int i;
    bool slash;

    len =strlen(str);
    slash = false;
    for(i=0;i<len;i++) //найдём знак дробной черты во введённой строке
     {
       if (str[i]=='/')
        {
          slash = true;
          break;
        }
     }
    if (slash == false) //если др. черта отсутствует, попробуем перевести строку в инт
     {
         long l;
         char *end;

         l = strtol(str, &end, 10);
         if (*end != '\0' || errno == ERANGE || l < INT_MIN || l > INT_MAX)
          {
              cout<<"\nVvedennaja stroka "<<str<<" ne javlyaetsya drobju. Drob ne sozdana!\n";
             //ВОТ ЗДЕСЬ НУЖНО, ЧТОБЫ ОБЪЕКТ НЕ БЫЛ СОЗДАН
              //delete this;
          }
         else
          {
              i = l;
              ch = i;
              zn = 1;
              cout<<"\nVvedennaja stroka "<<str<<" javlyaetsya drobju. Drob sozdana!\n";
          }
     }
 }

Последний раз редактировалось teapot; 04.12.2010 в 19:07.
teapot вне форума Ответить с цитированием
Старый 04.12.2010, 19:04   #2
Chica Bond
Пользователь
 
Регистрация: 15.03.2010
Сообщений: 31
По умолчанию

а ты пробывала запрещать неявный вызов конструктора с помощью explicit?? тогда думаю можно было бы если строка проходит проверку, то явно вызвать конструктор, а иначе ничего не должно происходить....
Chica Bond вне форума Ответить с цитированием
Старый 04.12.2010, 19:09   #3
teapot
Пользователь
 
Регистрация: 04.12.2010
Сообщений: 23
По умолчанию

М, раньше с таким не сталкивалась, но сейчас поищу в инете, как это делается, и попробую. Спасибо!
teapot вне форума Ответить с цитированием
Старый 04.12.2010, 19:17   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Я бы прикрутил к классу свойство Fail, которое показывало бы достоверные ли данные конструктор отработал. Если нет то освобождал объект сразу после его создания.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 04.12.2010, 19:37   #5
teapot
Пользователь
 
Регистрация: 04.12.2010
Сообщений: 23
По умолчанию

Цитата:
Сообщение от Chica Bond Посмотреть сообщение
а ты пробывала запрещать неявный вызов конструктора с помощью explicit?
Почитала, в моём случае это всё-таки не решит проблему

Цитата:
Сообщение от Stilet Посмотреть сообщение
Я бы прикрутил к классу свойство Fail, которое показывало бы достоверные ли данные конструктор отработал. Если нет то освобождал объект сразу после его создания.
Интересная мысль, она мне тоже в голову приходила, но по идее все свойства класса должны быть приватными. Тогда в головной программе у меня не должно быть возможности к ним обратиться. Эх, если ничего не придумаю, придётся нарушить-таки основопологающие принципы ООП)

Цитата:
Сообщение от Stilet Посмотреть сообщение
Я бы прикрутил к классу свойство Fail, которое показывало бы достоверные ли данные конструктор отработал. Если нет то освобождал объект сразу после его создания.
Хотя можно тогда воткнуть функцию, которая возвращает значение этого свойства. Спасибо)

Последний раз редактировалось Stilet; 04.12.2010 в 19:59.
teapot вне форума Ответить с цитированием
Старый 04.12.2010, 20:25   #6
still_alive
Great Code Monkey
Форумчанин
 
Аватар для still_alive
 
Регистрация: 09.08.2007
Сообщений: 533
По умолчанию

Цитата:
Сообщение от teapot
Вопрос, наверное, глупый)Можно ли как-то прервать создание объекта из конструктора, чтобы потом нельзя было к нему обратиться?
...
Хотя можно тогда воткнуть функцию, которая возвращает значение этого свойства. Спасибо)
Функция - это неудобно. Клиентскому коду придется все время проверять - а что же эта функция вернула? А если в одном месте вы это забудете проверить, то несколько дней жесткой отладки (для проекта нормального размера) гарантированы.
Просто выбрасывайте исключение с понятным сообщением. И еще следите, чтобы не было утечек памяти.
still_alive вне форума Ответить с цитированием
Старый 04.12.2010, 21:10   #7
teapot
Пользователь
 
Регистрация: 04.12.2010
Сообщений: 23
По умолчанию

Цитата:
Сообщение от still_alive Посмотреть сообщение
Функция - это неудобно. Клиентскому коду придется все время проверять - а что же эта функция вернула? А если в одном месте вы это забудете проверить, то несколько дней жесткой отладки (для проекта нормального размера) гарантированы.
Просто выбрасывайте исключение с понятным сообщением. И еще следите, чтобы не было утечек памяти.
Вот! Можно и исключение. Только где? Если в самом конструкторе, то проблема не решена, так как объект снова будет создан независимо от того, выпало исключение или нет. Если я правильно понимаю, память под объект выделяется сразу при вызове конструктора, а потом уже свойства объекта заполняются какими-то данными после выполнения кода конструктора. И если даже что-то там в конструкторе не сработает, объект так и останется висеть.

А если делать обработку исключения в главном модуле, то это, по сути, ничем не отличается от проверки свойства класса, только писать больше.

Или вы что-то другое имеете ввиду? Я, откровенно говоря, пока не сильно владею всеми этими делами.
teapot вне форума Ответить с цитированием
Старый 04.12.2010, 21:14   #8
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Клиентскому коду придется все время проверять - а что же эта функция вернула?
Ну разве лишний if() помешает?
Зато программист будет однозначно знать как обработать такую ситуацию, а вдруг ему нужно при таком выполнить какие-то его особые действия? В таком случае он будет ругать предусмотренное в конструкторе исключение на чем свет стоит (по себе знаю, как достают нежданчиковые исключения, которых не всегда удобно перехватывать)
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 04.12.2010, 21:37   #9
still_alive
Great Code Monkey
Форумчанин
 
Аватар для still_alive
 
Регистрация: 09.08.2007
Сообщений: 533
По умолчанию

Цитата:
Сообщение от teapot Посмотреть сообщение
Если в самом конструкторе, то проблема не решена, так как объект снова будет создан независимо от того, выпало исключение или нет. Если я правильно понимаю, память под объект выделяется сразу при вызове конструктора, а потом уже свойства объекта заполняются какими-то данными после выполнения кода конструктора. И если даже что-то там в конструкторе не сработает, объект так и останется висеть.
А если делать обработку исключения в главном модуле, то это, по сути, ничем не отличается от проверки свойства класса, только писать больше.
С++ не позволяет существовать частично созданным объектам. Если конструктор прерывается исключением, то можно считать, что этого объекта никогда не существовало. Он, так сказать, родился мертвым) С++ удаляет объект и чистит за ним стек, а вот освободить при необходимости динамическую память нужно вам перед выбросом исключения, дабы избежать утечек памяти.

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

Цитата:
Сообщение от Stilet
Ну разве лишний if() помешает?
Лишний if не помешает. Помешает забытый, но не лишний if В этом случае он может быть именно таким)

Цитата:
Сообщение от Stilet
Зато программист будет однозначно знать как обработать такую ситуацию, а вдруг ему нужно при таком выполнить какие-то его особые действия? В таком случае он будет ругать предусмотренное в конструкторе исключение на чем свет стоит (по себе знаю, как достают нежданчиковые исключения, которых не всегда удобно перехватывать)
Поставить try-catch, чтобы перехватить исключение нужного класса и в обработчике что-то сделать особенное (там оторвать что-нибудь кривое у юзера), совсем не сложно.
А нежданчиковых исключений не должно быть - они должны быть документированы, к тому же в большинстве вы все равно должны писать код, безопасный и нейтральный по отношению к исключениям (если никогда с таким не встречались - http://www.insidecpp.ru/art/15/ - правда описано не очень, в Саттере куда лучше).
still_alive вне форума Ответить с цитированием
Старый 04.12.2010, 21:40   #10
Ru_DoLF
Ubuntu 10.04
Пользователь
 
Аватар для Ru_DoLF
 
Регистрация: 15.07.2010
Сообщений: 51
По умолчанию

teapot В ООП так не делают. Как я понял вам надо реализовать класс обыкновенной дроби. Если какой-либо объект в программе становится "некорректным" не надо его удалять из памяти, пометьте его как "некорректный".
Цитата:
но по идее все свойства класса должны быть приватными
а зачем геттеры придумали?)

Вообщем вот
Код:
#include <iostream>

using namespace std;

class Fraction
{
public:
  Fraction();
  
  bool setValue(char *fraction);
  bool setValue(int numerator, int denominator);

  bool isValid();

private:
  int mNumerator;
  int mDenominator;
  bool mValidity;
};

bool Fraction::isValid()
{
  return mValidity;
}

bool Fraction::setValue(char *fraction)
{
  //Извращаемся и пилим строку
  //Это я оставляю вам :)
  return true;
}

bool Fraction::setValue(int numerator, int denominator)
{
  //легким движением руки создаем дробь

  if (denominator == 0)
    return false;

  mNumerator = numerator;
  mDenominator = denominator;

  return true;
}

Fraction::Fraction()
{
  mNumerator = 0;
  mDenominator = 1;
  
  mValidity = true;
}

int main()
{
  Fraction frac;
  
  if(frac.setValue(1, 7))
    cout << "It's ok" << endl;
  else
    cout << "Smth wrong..." << endl;

  if(frac.setValue(1, 0))
    cout << "It's ok" << endl;
  else
    cout << "Smth wrong..." << endl;

  return 0;
}
Язык образует среду мышления и формирует представление о том, о чем мы думаем (Б. Л. Уорф)
Ru_DoLF вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Автоматическое преобразование на основе первого аргумента конструктора в вызов самого конструктора jennya Visual C++ 8 03.10.2010 19:03
Как прервать выполнение операции? iskurt Помощь студентам 9 29.03.2010 18:46
Прервать выполнение функции? Как? TwiX Общие вопросы Delphi 9 28.09.2009 16:36
Как прервать внешний цикл? AndreyF Общие вопросы Delphi 15 15.06.2009 17:46
delphi 7, как прервать выполнение программы Altera Софт 3 27.07.2008 15:14