Перехватить неявный конструктор копирования C ++ или вызвать его функциональность

Дано:

class Foo {

private:
static int cntFoos;

//... stuff...

public:
Foo() { cntFoos++; }
~Foo() { cntFoos--; }
};

… где «материал» может быть любым набором свойств. (Идея состоит в том, чтобы иметь счетчик экземпляров этого класса)

Затем:

Foo aFoo;
Foo twoFoo=aFoo;

Запустит конструктор автоматического копирования, и, таким образом, я пропущу этот счет.

Есть ли способ сохранить счетчик, отражающий новые экземпляры, созданные автоматически? Если я реализую явный конструктор копирования, мне придется присваивать все свойства одно за другим. Однако я хочу мелкая, членная копия. Мне не нужно выполнять глубокое копирование, поэтому кажется, что для реализации явного конструктора копирования требуется много работы.

5

Решение

Поскольку для большинства членов требуется поведение по умолчанию и требуется специальная обработка только для одного (статического) члена, почему бы не инкапсулировать эту специальную обработку в свой собственный класс и не сделать переменную-член этого класса? Как это:

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 шаблон, чтобы разные классы могли легко иметь свои собственные числа экземпляров.
  • Для C ++ 11 вы также захотите предоставить конструктор перемещения и оператор присваивания перемещения для 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.
5

Другие решения

Извините, вам нужно будет перегрузить и скопировать вручную.

Если вы действительно, действительно, действительно против этого, вы можете использовать хак, где вы создаете абстрактный родительский класс со статическим счетчиком и переопределенным конструктором копирования, а также дочерний класс с вашими действительными членами данных и неявным конструктором поверхностного копирования.

Вы также можете воспользоваться несколько менее хакерским подходом инкапсулированного класса. Сохраните значения, которые вы хотите поверхностно скопировать, в инкапсулированном классе, а затем, при реализации конструктора явного копирования внешнего класса, сделайте поверхностную копию внутреннего класса, используя его неявный конструктор копирования.

5

По вопросам рекламы [email protected]