Дано:
class Foo {
private:
static int cntFoos;
//... stuff...
public:
Foo() { cntFoos++; }
~Foo() { cntFoos--; }
};
… где «материал» может быть любым набором свойств. (Идея состоит в том, чтобы иметь счетчик экземпляров этого класса)
Затем:
Foo aFoo;
Foo twoFoo=aFoo;
Запустит конструктор автоматического копирования, и, таким образом, я пропущу этот счет.
Есть ли способ сохранить счетчик, отражающий новые экземпляры, созданные автоматически? Если я реализую явный конструктор копирования, мне придется присваивать все свойства одно за другим. Однако я хочу мелкая, членная копия. Мне не нужно выполнять глубокое копирование, поэтому кажется, что для реализации явного конструктора копирования требуется много работы.
Поскольку для большинства членов требуется поведение по умолчанию и требуется специальная обработка только для одного (статического) члена, почему бы не инкапсулировать эту специальную обработку в свой собственный класс и не сделать переменную-член этого класса? Как это:
template<typename T>
class InstanceCounter
{
public:
static int Count;
// Automatically invoked when a class containing it is created.
InstanceCounter() { Count++; }
// Automatically invoked when a class containing it is destroyed.
~InstanceCounter() { Count--; }
// Automatically invoked when a class containing it is copy-constructed.
InstanceCounter(const InstanceCounter& rhs) { Count++; }
// No need to override operator=
// Allow this counter to be used as an int.
operator int() const { return Count; }
};
template<typename T>
int InstanceCounter<T>::Count;
class Foo
{
public:
InstanceCounter<Foo> count;
};
Замечания по реализации:
InstanceCounter
шаблон, чтобы разные классы могли легко иметь свои собственные числа экземпляров.InstanceCounter
,В качестве альтернативы и, возможно, лучше, используя идиому CRTP:
template<typename T>
class InstanceCounted
{
public:
static int InstanceCount;
// Automatically invoked when a class containing it is created.
InstanceCounted() { InstanceCount++; }
// Automatically invoked when a class containing it is destroyed.
~InstanceCounted() { InstanceCount--; }
// Automatically invoked when a class containing it is copy-constructed.
InstanceCounted(const InstanceCounted& rhs) { InstanceCount++; }
// No need to override operator=
};
template<typename T>
int InstanceCounted<T>::InstanceCount;
class Foo : public InstanceCounted<Foo>
{
// insert class contents here
};
// Now we can access Foo::InstanceCount.
Извините, вам нужно будет перегрузить и скопировать вручную.
Если вы действительно, действительно, действительно против этого, вы можете использовать хак, где вы создаете абстрактный родительский класс со статическим счетчиком и переопределенным конструктором копирования, а также дочерний класс с вашими действительными членами данных и неявным конструктором поверхностного копирования.
Вы также можете воспользоваться несколько менее хакерским подходом инкапсулированного класса. Сохраните значения, которые вы хотите поверхностно скопировать, в инкапсулированном классе, а затем, при реализации конструктора явного копирования внешнего класса, сделайте поверхностную копию внутреннего класса, используя его неявный конструктор копирования.