Вы не можете переопределить статический метод, таким образом делание его абстрактный было бы бессмысленно. Кроме того, статический метод в абстрактном классе принадлежал бы тому классу, а не переопределяющему классу, так не мог использоваться так или иначе.
You can use pragma directives to save and restore the new macro when undefing for overloads. See [MSDN](http://msdn.microsoft.com/en-us/library/hsttss76(VS.71).aspx) for the exact syntax.
E.g.
#pragma push_macro("new")
#undef new
void FAR* operator new(size_t cb);
#pragma pop_macro("new")
You can put these in headers, e.g.
begin_new_override.h:
#ifdef new
#define NEW_WAS_DEFINED
#pragma push_macro("new")
#undef new
#endif
end_new_override.h:
#ifdef NEW_WAS_DEFINED
#undef NEW_WAS_DEFINED
#pragma pop_macro("new")
#endif
And then
#include "begin_new_override.h"
void FAR* operator new(size_t cb);
#include "end_new_override.h"
Попробовать
#undef новый
перед определением класса
а затем #define new new ...
снова после.
Вместо того, чтобы определять new как нечто иное, почему бы не перегрузить оператор new?
Добавьте эти определения функций где-нибудь в глобальном пространстве имен:
// operator new overloads
void* operator new( const size_t size, const char* file, int line) throw();
void* operator new( const size_t size, const size_t align, const char* file, int line) throw();
void* operator new[]( const size_t size, const char* file, int line) throw();
void* operator new[]( const size_t size, const size_t align, const char* file, int line) throw();
// can't easily overload operator delete
void operator delete( void* ptr ) throw();
void operator delete[]( void* ptr ) throw();
// matched to the operator new overload above in case of exceptions thrown during allocation
void operator delete( void* ptr, const char* file, int line) throw();
void operator delete[]( void* ptr, const char* file, int line) throw();
void operator delete( void* ptr, const size_t align, const char* file, int line) throw();
void operator delete[]( void* ptr, const size_t align, const char* file, int line) throw();
// global new/delete
void* operator new( size_t size ) throw();
void* operator new( size_t size, const std::nothrow_t& ) throw();
void* operator new( size_t size, size_t align ) throw();
void* operator new( size_t size, size_t align, const std::nothrow_t& ) throw();
void* operator new[]( size_t size ) throw();
void* operator new[]( size_t size, const std::nothrow_t& ) throw();
void operator delete( void* ptr, const std::nothrow_t&) throw();
void operator delete[]( void* ptr, const std::nothrow_t&) throw();
Затем вы можете определить свой собственный новый макрос, который обращается к неглобальным версиям и реализует глобальные версии, чтобы утверждать или предупреждать, если они вызваны (чтобы поймать что-то проскальзывающее).
#define MY_NEW(s) new(s, __FILE__, __LINE__)
Ваши перегрузки на уровне класса будут работать должным образом, если вы вызовете 'new' непосредственно на класс. Если вы хотите вызвать MY_NEW в классе, вы можете, но вам придется переопределить перегрузку в классе в соответствии с вашим новым.
Переопределение new
через #define
на уровне препроцессора - плохая идея, по моему опыту - вы не только нарушаете оператор new
, но также размещение new
и, вероятно, несколько других вещей.
Если все эти макросы FILE и LINE расширяются повсюду, ваши разделы .rodata и .data переполняются строками файлов и номерами строк. , и генерирует намного больше кода за вызов.
Намного лучше (если приложить больше усилий заранее), чтобы воспользоваться преимуществом существования отладочной информации (например, .pdb
файл) и использовать что-то вроде ] DbgHelp
библиотека StackWalk64 для сбора информации о стеке.
Перегрузите различные комбинации глобального оператора new и оператора delete (массив, nothrow и т. Д.),пусть они сохраняют и освобождают информацию стека по мере выделения и освобождения памяти.
Вы даже можете сохранить эту информацию в такой структуре, как std :: map
Поскольку вы записываете весь стек для любого заданного выделения, вы можете сделать несколько изящных древовидный анализ, группировка распределений (утечки или другие) по «функциям и потомкам» ... И иногда легче отследить сложные утечки, если вы знаете весь стек по времени их распределения.
только будьте осторожны, чтобы не записывать аллоки, вызванные вставками карты (глобальной блокировки может быть достаточно для однопоточного приложения, многопоточность оставлена в качестве упражнения для читателя).Поскольку вы записываете все стек для любого заданного выделения, вы можете провести изящный древовидный анализ, сгруппировав выделения (утечки или иначе) по «функциям и потомкам» ... И иногда легче отслеживать сложные утечки, если вы знаете весь стек по времени их выделения.
только будьте осторожны, чтобы не записывать аллоки, вызванные вставками карты (глобальной блокировки может быть достаточно для однопоточного приложения, многопоточность оставлена в качестве упражнения для читателя).Поскольку вы записываете все стек для любого заданного выделения, вы можете провести изящный древовидный анализ, сгруппировав выделения (утечки или иначе) по «функциям и потомкам» ... И иногда легче отслеживать сложные утечки, если вы знаете весь стек по времени их выделения.
И иногда легче отследить сложные утечки, если вы знаете весь стек по времени их распределения. И иногда легче отследить сложные утечки, если вы знаете весь стек по времени их распределения.