1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.

C++ и оператор new

Тема в разделе "Программирование", создана пользователем БульЁн, 11.10.10.

  1. БульЁн

    БульЁн Активный участник

    1.241
    0
    Может кто знает.



    есть класс допустим A

    есть код
    A *a;
    a=new A()


    если в конструкторе A произошла ошибка, ну допустим при открытии файла, вообщем произошло условие при котором объект а недействительный

    Возможно ли, чтобы оператор new в таком случае вернул NULL ?
     
  2. sp_r00t

    sp_r00t Активный участник

    24.924
    1
    По идее должен стрелять исключением. А то произойдет обращение по адресу NULL и вот Вам segmentation fault...
     
  3. panda-34

    panda-34 Активный участник

    1.589
    0
    Дык в чем проблема-то?
    void* operator new (size_t size)
    {
    try
    {
    return ::new MyClass();
    }
    catch (...)
    {
    return NULL;
    }
    }
     
  4. sp_r00t

    sp_r00t Активный участник

    24.924
    1
    panda-34, так то так, но тогда возникает резонный вопрос - зачем? В дальнейшем обязательно придется проверять указатель на NULL, и обрабатывать эту ситуацию - так не проще сразу перехватить эксепшн и обработать?
     
  5. panda-34

    panda-34 Активный участник

    1.589
    0
    sp_r00t,
    Неправильно. Вопрос должен у Бульёна возникать. А я ответ даю. Иногда приходится делать вещи, которые для знающих людей являются полным бредом. Но приходится. И всегда, вместо того, чтобы просто дать четкий ответ на четкий вопрос, начинается рассусоливание: да это все не так, да это все по другому надо делать. И exception далеко не всегда проще перехватить и обработать. Я, вот, последний раз писал на C++ для микроконтроллера, там даже от конструкторов пришлось отказаться и сделать свою "фабрику объектов" на статической функции, т.к. конструктор увеличивал размер прошивки аж на 4 килобайта и расходовал херову кучу RAM.
     
  6. sp_r00t

    sp_r00t Активный участник

    24.924
    1
    Я понимаю:)
    Собственно мой вопрос правильнее было бы топикстартеру адресовать - ну вот любопытно стало, для чего такой замут?:)
     
  7. IvUs

    IvUs Активный участник

    10.986
    54
    Лучше не пихать в конструктор ошибкогенерящий код. И тогда вопросы подобные этому просто не возникают.
     
  8. БульЁн

    БульЁн Активный участник

    1.241
    0
    чтобы не разносить код для создания объекта по разным функциям,
    ну например

    A *a;
    BOOL bRet;
    a=new A();
    if (a!=NULL)
    bRet=a->Init(prm);
    if (bRet!=FALSE)
    { //объект создан
    }

    ---------- Сообщение добавлено 12.10.2010 20:40 ----------

    к сожалению он весь такой :(

    ну разве
    a=0; //всегда будет работать :)
     
  9. IvUs

    IvUs Активный участник

    10.986
    54
    А больше в конструктор ничего и не нужно класть.

    Вот это как раз гораздо надежнее гемора с кастомными new, исключениями и прочими радостями типа наполовину отработавшего конструктора из 1000 строк.
    Особенно, если сделать конструктор защищенным и сложить все эти строчки в статическую функцию-фабрику - тогда абсолютно все экземпляры будут создаваться в одном единственном месте.
     
  10. БульЁн

    БульЁн Активный участник

    1.241
    0
    :)
     
  11. sp_r00t

    sp_r00t Активный участник

    24.924
    1
    Фишка в том, что как это сделать без кастомного new, исключений и прочих радостей?
     
  12. IvUs

    IvUs Активный участник

    10.986
    54
    Очень просто. Если в конструкторе только инициализируются переменные и ничего более, то смысла кастомизировать new нет. И без исключений можно обойтись (я обхожусь), либо все их легко локализовать в фабрике.
    Лично я пользуюсь конструкциями типа:

    Код:
    [/FONT]
    [FONT=Courier New]class CMyClass[/FONT]
    [FONT=Courier New]{[/FONT]
    [FONT=Courier New]protected:[/FONT]
    [FONT=Courier New]FILE* m_pFile;
    [INDENT]CMyClass(void)
    [/INDENT][/FONT]
    [INDENT][FONT=Courier New]:m_pFile(NULL)[/FONT]
    [FONT=Courier New]{[/FONT]
    [FONT=Courier New]}[/FONT]
    [/INDENT][FONT=Courier New]virtual int Init(char* pcFileName)[/FONT]
    [FONT=Courier New]{//функция на 1000 строк.[/FONT]
    [INDENT][FONT=Courier New]m_pFile = fopen(pcFileName, "r");[/FONT]
    [FONT=Courier New]//todo: остальные 990 строк...[/FONT]
     
    [FONT=Courier New]return (m_pFile!=NULL);[/FONT]
    [/INDENT][FONT=Courier New]}[/FONT]
    [FONT=Courier New]public:[/FONT]
    [FONT=Courier New]virtual ~CMyClass()[/FONT]
    [FONT=Courier New]{[/FONT]
    [INDENT][FONT=Courier New]Close();[/FONT]
    [/INDENT][FONT=Courier New]}[/FONT]
    [FONT=Courier New]virtual void Close()[/FONT]
    [FONT=Courier New]{[/FONT]
    [INDENT][FONT=Courier New]if(m_pFile)[/FONT]
    [INDENT][FONT=Courier New]{ fclose(m_pFile);m_pFile=NULL;}[/FONT]
    [/INDENT][/INDENT][FONT=Courier New]}[/FONT]
    [FONT=Courier New]static CMyClass* CreateInstance(char* pcFileName)[/FONT]
    [FONT=Courier New]{[/FONT]
    [INDENT][FONT=Courier New]int r;[/FONT]
    [FONT=Courier New]CMyClass* pInstance = new CMyClass();[/FONT]
    [FONT=Courier New]try[/FONT]
    [FONT=Courier New]{[/FONT]
    [INDENT][FONT=Courier New]r = pInstance->Init(pcFileName);[/FONT]
    [/INDENT][FONT=Courier New]}[/FONT]
    [FONT=Courier New]catch(...)[/FONT]
    [FONT=Courier New]{[/FONT]
    [INDENT][FONT=Courier New]r=0;[/FONT]
    [/INDENT][FONT=Courier New]}[/FONT]
    [FONT=Courier New]if(!r)[/FONT]
    [FONT=Courier New]{//наша фабрика работает по принципу "все или ничего"[/FONT]
    [INDENT][FONT=Courier New]//если инициализация обломалась, то херим объект и ничего наружу не отдаем:[/FONT]
    [FONT=Courier New]delete pInstance;[/FONT]
    [FONT=Courier New]pInstance = NULL;[/FONT]
    [/INDENT][FONT=Courier New]}[/FONT]
    [FONT=Courier New]return pInstance;[/FONT]
    [FONT=Courier New]}[/FONT]
    [/INDENT][FONT=Courier New]};[/FONT]
     
    [FONT=Courier New]int main(int argc, char* argv[])[/FONT]
    [FONT=Courier New]{[/FONT]
    [INDENT][FONT=Courier New]CMyClass* pClass = CMyClass::CreateInstance("c:\\readme.txt");[/FONT]
    [FONT=Courier New]if(!pClass)[/FONT]
    [FONT=Courier New]{[/FONT]
    [FONT=Courier New]printf("какая-то беда с созданием экземпляра CMyClass\n");[/FONT]
    [FONT=Courier New]return -1;[/FONT]
    [FONT=Courier New]}[/FONT]
    [FONT=Courier New]//todo: что-то полезное.[/FONT]
    [FONT=Courier New]return 0;[/FONT]
    [/INDENT][FONT=Courier New]}[/FONT]
    [FONT=Courier New]
     
  13. The Last Winged

    The Last Winged Активный участник

    11.862
    48
    panda-34, Недавно сильно ковырял SMF - там код в стиле бейсика с goto. И оправдание как у вас: "Но приходится."
    Ктулху с Исусом заставляют?


    А смысл конструктору иметь более десятка-другого строк?
    Не проще ли сразу нормально писать?
     
  14. IvUs

    IvUs Активный участник

    10.986
    54
    о чем и спик. :)