#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 «Вы не можете объявить класс или структуру внутри себя, но вы все равно можете создать экземпляр внутри функции-члена, как он описал в своих примерах выше» — я предлагал по-другому?