С ++ класс конструктор путают о моем коде [duplicate]

По крайней мере, вплоть до CSS3, включая CSS3, вы не можете выбрать это. Но это может быть сделано довольно легко в настоящее время в JS, вам просто нужно добавить немного ванильного JavaScript, обратите внимание, что код довольно короткий.

      cells = document.querySelectorAll('div');
              [].forEach.call(cells, function (el) {
              //console.log(el.nodeName)
                if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
                console.log(el)};
            });
            <div>Peter</div>
            <div><a href="#">Jackson link</a></div>
            <div>Philip</div>
            <div><a href="#">Pullman link</a></div>

169
задан paxos1977 30 November 2016 в 21:04
поделиться

8 ответов

Для членов класса POD это не имеет никакого значения, это всего лишь вопрос стиля. Для членов класса, которые являются классами, тогда он избегает ненужного вызова конструктора по умолчанию. Рассмотрим:

class A
{
public:
    A() { x = 0; }
    A(int x_) { x = x_; }
    int x;
};

class B
{
public:
    B()
    {
        a.x = 3;
    }
private:
    A a;
};

В этом случае конструктор для B вызовет конструктор по умолчанию для A, а затем инициализирует a.x до 3. Лучшим способом для B ', чтобы напрямую вызвать конструктор A в списке инициализаторов:

B()
  : a(3)
{
}

Это вызвало бы только конструктор A A(int), а не его конструктор по умолчанию. В этом примере разница незначительна, но представьте, если вы сделаете это, когда конструктор по умолчанию A сделал больше, например, выделив память или открыв файлы. Вы не захотите делать это без необходимости.

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

class A
{
public:
    A(int x_) { x = x_; }
    int x;
}

class B
{
public:
    B() : a(3), y(2)  // 'a' and 'y' MUST be initialized in an initializer list;
    {                 // it is an error not to do so
    }
private:
    A a;
    const int y;
};
221
ответ дан Rakete1111 19 August 2018 в 09:55
поделиться
  • 1
    необходимо также для важного случая ссылки – 4pie0 6 May 2014 в 13:38
  • 2
    Почему бы не использовать & alpha; (3) & quot; или "a = A (3)"; в теле конструктора B по умолчанию? – Sergey 6 March 2015 в 11:07
  • 3
    Не могли бы вы объяснить, что вы имеете в виду с POD? – Jonas Stein 19 November 2015 в 12:12
  • 4
    @JonasStein POD - это четко определенный набор правил, касающихся простых структур данных (а не полных классов). Читайте FAQ для получения дополнительной информации: stackoverflow.com/questions/146452/what-are-pod-types-in-c – monkey0506 28 March 2016 в 04:02
  • 5
    @Sergey, конструктор по умолчанию A по-прежнему будет вызван. – Vassilis 2 May 2017 в 18:24

Синтаксис:

  class Sample
  {
     public:
         int Sam_x;
         int Sam_y;

     Sample(): Sam_x(1), Sam_y(2)     /* Classname: Initialization List */
     {
           // Constructor body
     }
  };

Необходимость списка инициализации:

 class Sample
 {
     public:
         int Sam_x;
         int Sam_y;

     Sample()     */* Object and variables are created - i.e.:declaration of variables */*
     { // Constructor body starts 

         Sam_x = 1;      */* Defining a value to the variable */* 
         Sam_y = 2;

     } // Constructor body ends
  };

в вышеуказанной программе. Когда выполняется конструктор класса, создаются Sam_x и Sam_y. Затем в корпусе конструктора определены эти переменные данных элемента.

Варианты использования:

  1. Константные и ссылочные переменные в классе

В C переменные должны быть определены во время создания. то же самое в C ++, мы должны инициализировать переменную Const и Reference во время создания объекта, используя список инициализации. если мы выполним инициализацию после создания объекта (внутри тела конструктора), мы получим ошибку времени компиляции.

  1. Объекты-члены класса Sample1 (базовый), которые не имеют конструктора по умолчанию
     class Sample1 
     {
         int i;
         public:
         Sample1 (int temp)
         {
            i = temp;
         }
     };
    
      // Class Sample2 contains object of Sample1 
     class Sample2
     {
      Sample1  a;
      public:
      Sample2 (int x): a(x)      /* Initializer list must be used */
      {
    
      }
     };
    

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

 1. Default constructor of Sample1 class
 2. Initialization list in Sample2 class which will call the parametric constructor of Sample1 class (as per above program)
  1. Имя параметра конструктора класса, и элемент данных класса одинаковы:
     class Sample3 {
        int i;         /* Member variable name : i */  
        public:
        Sample3 (int i)    /* Local variable name : i */ 
        {
            i = i;
            print(i);   /* Local variable: Prints the correct value which we passed in constructor */
        }
        int getI() const 
        { 
             print(i);    /*global variable: Garbage value is assigned to i. the expected value should be which we passed in constructor*/
             return i; 
        }
     };
    

Как и все мы знаете, локальная переменная имеет самый высокий приоритет, чем глобальная переменная, если обе переменные имеют одинаковое имя. В этом случае программа учитывает значение «i» {как левую, так и правую переменную. i.e: i = i} как локальная переменная в конструкторе Sample3 (), а переменная-член класса (i) переопределена. Чтобы избежать этого, мы должны использовать либо

  1. Initialization list 
  2. this operator.
0
ответ дан Eswaran Pandi 19 August 2018 в 09:55
поделиться

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

Если у вас есть ссылка или константное поле, или если один из используемых классов не имеет конструктора по умолчанию, вы должны использовать список инициализации.

5
ответ дан Jamal Zafar 19 August 2018 в 09:55
поделиться
// Without Initializer List
class MyClass {
    Type variable;
public:
    MyClass(Type a) {  // Assume that Type is an already
                     // declared class and it has appropriate 
                     // constructors and operators
        variable = a;
    }
};

Здесь компилятор выполнил следующие шаги для создания объекта типа MyClass 1. Конструктор типа сначала называется «a». 2. Оператор присваивания «Тип» вызывается внутри тела конструктора MyClass () для назначения

variable = a;
  1. . И тогда деструктор «Тип» вызывается для «a», поскольку он идет вне сферы действия. Теперь рассмотрим тот же код с конструктором MyClass () с Initializer List
    // With Initializer List
     class MyClass {
    Type variable;
    public:
    MyClass(Type a):variable(a) {   // Assume that Type is an already
                     // declared class and it has appropriate
                     // constructors and operators
    }
    };
    
    . С помощью списка инициализаторов следуют шаги, за которыми следует компилятор: Копировать конструктор класса «Тип» вызывается для инициализации: variable (a). Аргументы в списке инициализаторов используются для непосредственного копирования «переменной». Деструктор «Тип» вызывается для «а», поскольку он выходит за рамки.
2
ответ дан ketan 19 August 2018 в 09:55
поделиться
  • 1
    Хотя этот фрагмент кода может решить вопрос, в том числе объяснение из кода действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода. Также попробуйте не толковать код с пояснительными комментариями, что уменьшает читаемость кода и объяснений! meta.stackexchange.com/q/114762/308249 – davejal 25 November 2015 в 04:12
  • 2
    Пожалуйста, напишите ваше собственное понимание или просто поделитесь ссылкой на исходный источник (здесь, geeksforgeeks.com), а не просто скопируйте его. – yuvi 3 December 2016 в 03:51

Рядом с проблемами производительности есть еще один очень важный вопрос, который я бы назвал легкостью и расширяемостью кода.

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

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

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

struct T
{
    T() { a = 5; }
private:
    int a;
};

Затем вы решили квалифицировать a как const, если бы вы использовали список инициализации с самого начала, тогда это было однострочное изменение, но с T, как указано выше, также требуется выкопать конструктор defi для удаления назначения:

struct T
{
    T() : a(5) {} // 2. that requires changes here too
private:
    const int a; // 1. one line change
};

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

7
ответ дан mloskot 19 August 2018 в 09:55
поделиться

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

38
ответ дан Naveen 19 August 2018 в 09:55
поделиться
  • 1
    То же самое касается константных членов, которые я считаю. – Richard Corden 29 May 2009 в 17:44
  • 2
    yes, Невозможно использовать назначение для изменения константных переменных, чтобы оно было инициализировано. – Hareen Laks 14 April 2018 в 13:53
  1. Инициализация базового класса

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

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

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

  1. Инициализация субообъектов, которые имеют только параметризованные конструкторы
  2. Эффективность

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

  1. Инициализация нестатических константных членов данных

Если нестатические члены данных const в вашем класс имеют стандартные конструкторы & amp; вы не используете список инициализаторов конструктора, вы не сможете их инициализировать до предполагаемого состояния, поскольку они будут инициализированы в их состоянии по умолчанию.

  1. Инициализация элементов опорных данных

Элементы ссылочных данных должны быть инициализированы, когда компилятор входит в конструктор, поскольку ссылки не могут быть просто объявлены & amp; инициализируется позже. Это возможно только с помощью списка инициализаторов конструктора.

12
ответ дан yuvi 19 August 2018 в 09:55
поделиться
0
ответ дан Yi Wang 30 October 2018 в 22:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: