Я могу заставить новый экземпляр класса C++ перестать работать, если определенные условия в конструкторе не соблюдены?

Насколько я понимаю, когда новый класс инстанцируют в C++, указатель на новый класс возвращается, или ПУСТОЙ УКАЗАТЕЛЬ, если существует недостаточно память. Я пишу класс, который инициализирует связанный список в конструкторе. Если бы существует ошибка при инициализации списка, я хотел бы, чтобы класс instantiator возвратил ПУСТОЙ УКАЗАТЕЛЬ.

Например:

MyClass * pRags = new MyClass;

Если бы связанному списку в конструкторе MyClass не удается инициализировать правильно, я хотел бы, чтобы педанты равнялись ПУСТОМУ УКАЗАТЕЛЮ. Я знаю, что могу использовать флаги и дополнительные проверки, чтобы сделать это, но я хотел бы избежать этого, если это возможно.
Кто-либо знает о способе сделать это?

5
задан mskfisher 2 November 2011 в 14:48
поделиться

3 ответа

Обычный подход здесь - вызвать исключение (и обработать его где-нибудь выше).

Одним из преимуществ механизма исключений является то, что он позволяет генерировать исключение из конструктора класса. В этом случае вы никогда не дойдете до ситуации, когда указатель возвращается на недопустимый. Вы «получите управление» в соответствующем блоке catch. Если бы указатель был объявлен только в блоке try (или в каком-либо другом методе, вызванном блоком try), он был бы вне вашей области видимости в этом блоке catch.

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

Вот пример (я занимаюсь Java последние 10 лет, поэтому мой код C ++ ниже, скорее всего, здесь испорчен, возможно, кто-нибудь сможет отредактировать его для меня)

// Begin C++ code written by a Java programmer... :)
class Myclass
{
   public:
      Myclass(int length)
      {
          if(length<=0) throw BadBufferSizeException("Bla bla bla");         
          this->buffer = (char*)malloc(length*sizeof(char)); // don't remember the new syntax
      }

      void doSomething()
      {
          // Code for placing stuff in the buffer
      }
    private:
      char* buffer;
};


int main()
{
   try
   { 
     int len;
     len = getLengthFromUser();
     MyClass* pMyClass = new MyClass(len);
     myClass->doSomething();
    } catch(const Exception & e)
    {
       // Whatever... Note how pMyClass is not even accessible here
    }
}

Обратите внимание, что если вы определили pMyclass как null за пределами блока try, а затем переназначил его только в блоке try при создании класса, в случае сбоя вы, вероятно, все равно будете иметь значение null, но вы бы никогда не выполнили doSomething (). Если вас беспокоит инициализация, вы также можете переместить вызов doSomething () за пределы блока try-catch, но вы должны убедиться, что ваш указатель не равен нулю.

Также обратите внимание, что C ++ дает вам больше (слишком много?) Свободы, когда дело доходит до метания вещей, чем другие языки.Обычно мне нравится иметь иерархию классов исключений или использовать существующую библиотеку с такой иерархией.

16
ответ дан 18 December 2019 в 09:48
поделиться

Ваше понимание несколько устарело, поскольку Стандарт 1995 года предписывал использование исключений вместо возврата 0. Он также предусматривал серию методов nothrow , которые работают следующим образом: Foo * foo = new (nothrow) Foo; .

0
ответ дан 18 December 2019 в 09:48
поделиться

Стандартный способ конструктора указать ошибку - исключение.

Если по какой-то причине ваше приложение не может обрабатывать исключения и ему требуется возвращаемое значение NULL, вы можете заключить конструктор в фабричный метод следующим образом ...

class MyClass
{
    public:
        static MyClass* makeMyClass()           
        {
           MyClass* retval = NULL;
           try 
           {
              retval = new MyClass();
           }
           catch(std::exception& e)
           {
               // Report the exception;
               retval = NULL;
           }
           return retval;
       }
    // ....
    };
1
ответ дан 18 December 2019 в 09:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: