Создание экземпляра класса внутри функции-члена

#c #oop #recursion #instantiation

#c #ооп #рекурсия #создание экземпляра

Вопрос:

Безопасно ли создавать экземпляр класса внутри функции-члена этого класса? Например, допустим, у меня есть класс CMyClass с функцией-членом CMyClass::MemberFunc , и я хочу создать другой экземпляр CMyClass внутри CMyClass::MemberFunc .

 void CMyClass::MemberFunc( void )
{
    CMyClass * pMyClass = new CMyClass();
}
  

Это законно / безопасно? Я знаю, что это компилируется. Что меня беспокоит, так это рекурсия. Столкнусь ли я с ошибкой рекурсии при создании экземпляра CMyClass в первый раз из основного приложения?

 void main( void )
{
    static CMyClass * s_pMyClass = new CMyClass(); // Will this cause recursion?
}
  

Или рекурсия будет происходить только в том случае, если вызывается конкретная функция-член с дополнительным экземпляром класса?

 void CMyClass::MemberFunc( void )
{
    CMyClass * pMyClass = new CMyClass();
    pMyClass->MemberFunc(); // Pretty sure this will cause a recursive loop.
}
  

Другими словами, могу ли я безопасно создать экземпляр данного класса внутри функции-члена этого класса, при условии, что я не вызываю эту функцию-член второго экземпляра этого класса? Спасибо.

Ответ №1:

Это не более и не менее безопасно, чем создание экземпляра любого другого объекта. Обратите внимание, что в вашем примере внизу рекурсия строго основана на том факте, что метод вызывает сам себя; он будет повторяться бесконечно независимо.

В целом: все должно быть в порядке.

Ответ №2:

Функция (член), вызывающая саму себя, известна как рекурсия.

Это законно / безопасно?

 void CMyClass::MemberFunc( void )
{

    CMyClass * pMyClass = new CMyClass();

    delete pMyClass ;  // newly added.

}
  

Частично верно. Потому что каждая new операция должна сопровождаться delete операцией над конкретным экземпляром, чтобы вернуть ресурсы обратно в бесплатное хранилище. Кроме утечки памяти, приведенный выше фрагмент в порядке.

Или рекурсия будет происходить только в том случае, если вызывается конкретная функция-член с дополнительным экземпляром класса?

 void CMyClass::MemberFunc( void )
{
    CMyClass * pMyClass = new CMyClass();
    pMyClass->MemberFunc(); // Pretty sure this will cause a recursive loop.
}
  

Да, и через некоторое время у вас должна закончиться память, поскольку нет способа вызвать деструктор для конкретного экземпляра, поскольку CMyClass::MemberFunc вызывается рекурсивно. ( предполагая delete pMyClass; , что это оператор end в функции-члене)

Также нет необходимости помещать void в список аргументов, когда метод не получает никаких параметров. Я думаю, это C стиль.

Ответ №3:

Правильно, если вы явно не вызовете эту функцию-член из второго созданного экземпляра, вы не вызовете рекурсию. Конечно, рекурсия не всегда является чем-то плохим, пока у вас есть какое-то базовое условие для выполнения.

Комментарии:

1. Или, если это что-то глупое, например, создание нового экземпляра класса внутри конструктора, который вызывал бы конструктор и вызывал бесконечную рекурсию

Ответ №4:

Нет, это не вызовет рекурсию — ваш компилятор пометил бы это как ошибку, если бы это произошло. Я подозреваю, что вы действительно хотите создать статический экземпляр вашего класса (например, singleton). Можете ли вы опубликовать реальный пример использования, иллюстрирующий, что вы хотите сделать?

Комментарии:

1. Почему компилятор помечает рекурсию как ошибку? Это совершенно верный инструмент программирования. Единственный способ, которым он мог узнать, был ли он бесконечно рекурсивным, или что он вообще был рекурсивным в первую очередь, — это если он действительно проанализировал и попытался запустить код

2. @Dan Классы и структуры не могут быть объявлены рекурсивно в C .

3. Вы не можете объявить класс или структуру внутри себя, но вы все равно можете создать экземпляр внутри функции-члена, как он описал в своих примерах выше

4. И простым вариантом использования в реальном мире была бы функция копирования, которая возвращает новый экземпляр вызванного объекта, а не просто другой указатель или ссылку на него

5. @Dan «Вы не можете объявить класс или структуру внутри себя, но вы все равно можете создать экземпляр внутри функции-члена, как он описал в своих примерах выше» — я предлагал по-другому?