Объясните пустые функции класса в C ++ - PullRequest
1 голос
/ 03 августа 2011
class forums : public master{
public:
    forums() : next(0),prev(0) {}
}
  1. Объясните, пожалуйста, что конкретно означают функции next (0) и prev (0)?

  2. Что означает разделение функции запятой (,)? какой эффект дают пустые скобки {} рядом с этими функциями?

  3. Я новичок в C ++, и пытаюсь выяснить, что это значит или как предполагается использовать для этого способа написания функции?

как это специально предназначено для переопределения?

Ответы [ 5 ]

8 голосов
/ 03 августа 2011

Что у вас там есть «список инициализации».

Код устанавливает начальные значения членов next и prev экземпляра класса.

Этот код может вызывать функции конструктора, если next и prev являются экземплярами классов, или может просто присваивать им значения, если они являются примитивными типами.

Они разделены запятыми, потому что так выглядит синтаксис списков инициализации.

Пустые фигурные скобки означают тело конструктора forums - в этом примере ничего не происходит в самом конструкторе, поскольку работа выполняется в списке инициализации.

2 голосов
/ 03 августа 2011

1) Инициализирует next и prev до 0, как при инициализации, а не присваивании.

2) Это называется списком инициализатора конструктора.Без этого вам нужно было бы присвоить next & prev 0 в теле конструктора.Это не одно и то же.Вы должны понимать разницу между инициализацией объекта и назначением.Для некоторых типов, ссылок и объектов const список инициализаторов является обязательным.Для сложных объектов лучше использовать список инициализаторов, потому что при назначении объекта в теле конструктора вы будете платить за инициализацию объекта и его назначение.Для простых целочисленных типов нет никакой разницы, но для типов с конструкторами, потому что обычно присваивание почти так же дорого, как и инициализация.

Здесь тело пусто, потому что только next и prev требуют инициализации и ничего большедолжно быть сделано.

Кроме того, порядок инициализации членов очень строг, он происходит в порядке их объявления.Порядок, в котором вы записываете его в список инициализаторов, не имеет значения, это происходит в порядке декларирования.

Так важно понимать между инициализацией и назначением.

Также понимают объявления против определений.Много путаницы возникнет, если вы не поймете эти понятия.

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

1 голос
/ 06 августа 2011

Краткий ответ

Это конструктор с пустым телом и списком инициализации элемента , который инициализирует два элемента данных значением 0.

т.е.

  • class-name([ ctor-args ]) [ : member-init-list ] { [ ctor-body ] }

  • , где member-init-list равно member-name(args) [, member-name(args) [, ... ] ].

(Примечание: не фактические лексические грамматические конструкции C ++)


Длинный ответ

Фон

Примите следующие определения классов:

struct Base {};
struct Derived : Base {};

Возможно, вы уже знаете, что Derived происходит от Base.

Вы, возможно, уже знаете, что оба Derived и Base имеют синтезированный (неявно объявленный) конструктор по умолчанию (без аргументов). Конструктор Derived неявно / автоматически вызывает Base.

Теперь давайте добавим базовую функцию-член:

struct Derived : Base {
   void foo() {}
};

Я объявил и , которые определили этот член-функцию foo; его тело пусто, поэтому, когда вы вызываете его, ничего не происходит. Это довольно бессмысленно, но совершенно справедливо.

Теперь вместо этого давайте создадим наш собственный конструктор:

struct Derived : Base {
   Derived() {}
};

Это выглядит более знакомым. Это все еще [специальная] функция с пустым телом, и конструктор Base все еще вызывается неявно. Мы не изменили это.


Обработка данных членов

Давайте добавим некоторые элементы данных и установим их значение в нашем конструкторе:

struct Derived : Base {
   Derived() {
      x = 0;
      y = 0;
   }

   int x, y;
};

И x, и y будут иметь значение 0 после построения объекта. Это все еще фундаментальный C ++.

Но вы можете не знать, что вы не инициализируете эти элементы данных. Вы просто назначаете им после возможности их инициализации.

Фактически, члены данных встроенных типов не инициализируются неявно, поэтому давайте выберем лучший пример:

struct Derived : Base {
   Derived() /* HERE */ {
      x = "";
      y = "";
   }

   std::string x, y;
};

x и y неявно инициализируются до запуска кода в теле конструктора. Когда тело конструктора начинает работать, все члены, которые будут инициализированы, уже инициализированы , и базовый конструктор был вызван неявно.

Мы можем перехватить это поведение и предоставить наши собственные значения инициализации, написав список инициализаторов в том месте, где я написал /* HERE */ в предыдущем фрагменте. С помощью списка инициализатора элемента фрагмент выглядит следующим образом:

struct Derived : Base {
   Derived() : x(""), y("") {
      x = "";
      y = "";
   }

   std::string x, y;
};

Ничего себе! ХОРОШО; теперь мы инициализируем строки в "", и , а затем присваиваем им то же пустое значение в теле конструктора. Мы можем избавиться от этих заданий, тогда:

struct Derived : Base {
   Derived() : x(""), y("") {}

   std::string x, y;
};

Теперь тело конструктора пустое, но конструктор все еще делает вещи. Он неявно вызывает базовый конструктор и явно инициализирует элементы данных x и y пустой строкой.

И, поскольку std::string имеет конструктор по умолчанию, который делает то же самое, мы можем написать для краткости:

struct Derived : Base {
   Derived() : x(), y() {}

   std::string x, y;
};

Возвращаясь к исходному примеру, это относится и к объектам встроенных типов. Давайте рассмотрим два указателя:

struct Derived : Base {
   Derived() : next(0), prev(0) {}

   Derived* next;
   Derived* prev;
};

Обработка базовых классов

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

struct Derived : Base {
   Derived() : Base(), next(0), prev(0) {}

   Derived* next;
   Derived* prev;
};

Это довольно бессмысленно, если базовый конструктор не хочет аргументов:

struct Base {
   Base(int x) {}
};

struct Derived : Base {
   Derived() : Base(0), next(0), prev(0) {}

   Derived* next;
   Derived* prev;
};

Я надеюсь, что это было полезно.

1 голос
/ 03 августа 2011

Это не функция. Он имеет такую ​​же функциональность как:

forums()
{
    next = 0;
    prev = 0;
}

next и prev, вероятно, являются членами вашего базового класса.

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

1 голос
/ 03 августа 2011
...