Инкрементальный номер с использованием «Любопытно повторяющегося шаблона» - PullRequest
1 голос
/ 06 апреля 2011

Я хочу реализовать class Address, который при создании инициализирует его поле addr уникальным значением.Это значение должно увеличиваться на единицу каждый раз, когда я создаю экземпляр Address.

Давайте рассмотрим пример.После того, как следующий код был выполнен:

Address x;
Address y;

x.addr должно быть 1, а y.addr должно быть 2.

Для этого я подумал о Любопытно повторяющийся шаблон .Будет ли это возможно?Кроме того, существуют ли более простые методы для достижения того же поведения?

TIA, Jir

Ответы [ 5 ]

7 голосов
/ 06 апреля 2011

Вам это на самом деле не нужно, потому что вам не нужно захватывать уничтожение объекта. Вы заметите, что пример на этой странице Википедии содержит промежуточную сумму количества объектов данного типа, поэтому CRTP имеет две удобные функции:

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

Если вам просто нужно уникальное значение для каждого члена отдельного класса, то, кроме безопасности потоков, вы можете сделать это следующим образом:

int get_id() {
    static int counter = 0;
    return ++counter;
}

class Address {
    int addr;
  public:
    Address() : addr(get_id()) {}
};

Следуя примеру CRTP, вы можете использовать шаблон get_id и использовать Address в качестве аргумента, если у вас есть несколько классов для отслеживания, и вы хотите, чтобы у каждого из них было свое пространство идентификаторов.

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

template <typename Derived>
class unique_addr {
  protected:
    int addr;
    unique_addr() : addr(get_id<Derived>()) {}
};

class Address : public unique_addr<Address> {
};

class OtherAddress : public unique_addr<OtherAddress> {
};
1 голос
/ 06 апреля 2011

Это кажется излишним за то, что ты пытаешься сделать. Если все, что вам нужно, это уникальное значение, используйте статическое целое число и увеличивайте его каждый раз, когда вы создаете экземпляр объекта. Затем установите для этого экземпляра переменную для каждого экземпляра (т.е. не статичную).

0 голосов
/ 07 апреля 2011

Вы также можете использовать статический счетчик, внутренний для класса:

class Address
{
  static int s_Count; // define this variable in appropriate cpp file
  int addr;
public:
  Address () : addr(++ s_Count) {}
};
0 голосов
/ 06 апреля 2011
public class Address
{
    private static int addrCounter = 1;

    public int addr { get; private set; }

    public Address()
    {
        addr = addrCounter++;
    }
}
0 голосов
/ 06 апреля 2011

Конечно, вы можете сделать это точно так, как показано в статье Википедии, на которую вы ссылались.(За исключением того, что это не звучит так, как будто вы хотите уменьшить счетчик в dtor.) Или, если вам это нужно только для класса Address, вы можете просто сделать то, что реализация CRTP там делает как разовый:

static int n_addresses = 0;
class Address {
  int addr;
  Address() { addr = ++n_addresses; }
};

или что-то в этом роде.

...