Объектная реализация couting с использованием композиции в Stack Overflow

В более эффективном C ++ Мейерс описал способ подсчета экземпляров объектов с использованием базового класса для подсчета объектов (пункт 26). Можно ли реализовать тот же метод с использованием композиции, как показано ниже. Есть ли конкретное преимущество использования частного наследования и каковы недостатки использования композиции в этом случае.

PS: — Я повторно использовал код из более эффективного C ++ с небольшой модификацией.

    #ifndef COUNTERTEMPLATE_HPP_
#define COUNTERTEMPLATE_HPP_
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

template <class BeingCounted>
class Counted {
public:
static int ObjectCount(){return numOfObjects;}
Counted();
Counted(const Counted& rhs);
~Counted(){--numOfObjects;}
protected:
private:
static int numOfObjects;
static int maxNumOfObjects;
void init();
};

template<class BeingCounted> Counted<BeingCounted>::Counted()
{
init();
}

template<class BeingCounted> Counted<BeingCounted>::Counted(const Counted& rhs)
{
init();
}

template<class BeingCounted> void Counted<BeingCounted>::init()
{
if(numOfObjects>maxNumOfObjects){}
++numOfObjects;
}

class Printer
{
public:
static Printer* makePrinter(){return new Printer;};
static Printer* makePrinter(const Printer& rhs);
Counted<Printer>& getCounterObject(){return counterObject;}
~Printer();
private:
Printer(){};
Counted<Printer> counterObject;
Printer(const Printer& rhs){};
};

#endif /* COUNTERTEMPLATE_HPP_ */

2

Решение

Этот вопрос связан с

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


Частное наследование может использовать пустую оптимизацию базового класса:

class Printer0
{
Counted<Printer0> counterObject;
int m;
};

class Printer1 : Counter<Printer1>
{
int m;
};

Clang ++ и g ++ оба говорят sizeof(Printer0) == 8 а также sizeof(Printer1) == 4,

Причина в том, что члены данных должны иметь разные адреса,
но один пустой базовый класс не должен занимать память в объекте.
Так counterObject один байт большой, и int выравнивается до 4 байтов,
следовательно Printer0 выглядит так:

| | X X | |
0 1 2 3 4 5 6 7 8 9
^ ~~~~~~~~ м
^ ~~~ padding
^ ~~~ counterObject
2

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

Композиция вынуждает вас «загрязнять» код вашего класса метаданными (то есть счетчиком), которые не связаны с его основным бизнесом, по моему мнению, делая код менее читабельным для этого случая. Также смотрите ответ @dyp относительно технического аспекта оптимизации пустого класса.

0

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