По крайней мере, вплоть до 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>
Для членов класса 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;
};
Синтаксис:
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. Затем в корпусе конструктора определены эти переменные данных элемента.
Варианты использования:
В C переменные должны быть определены во время создания. то же самое в C ++, мы должны инициализировать переменную Const и Reference во время создания объекта, используя список инициализации. если мы выполним инициализацию после создания объекта (внутри тела конструктора), мы получим ошибку времени компиляции.
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)
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.
Прежде чем запустить тело конструктора, вызывается все конструкторы для его родительского класса, а затем для его полей. По умолчанию вызываются конструкторы без аргументов. Списки инициализации позволяют вам выбрать, какой конструктор вызывается и какие аргументы получает конструктор.
Если у вас есть ссылка или константное поле, или если один из используемых классов не имеет конструктора по умолчанию, вы должны использовать список инициализации.
// 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;
// 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). Аргументы в списке инициализаторов используются для непосредственного копирования «переменной». Деструктор «Тип» вызывается для «а», поскольку он выходит за рамки. Рядом с проблемами производительности есть еще один очень важный вопрос, который я бы назвал легкостью и расширяемостью кода.
Если 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
};
Не секрет, что техническое обслуживание намного проще и менее подвержено ошибкам, если код был написан не «обезьяной кода», а инженером, который принимает решения на основе более глубоких рассмотрение того, что он делает.
Помимо упомянутых выше причин производительности, если ваш класс хранит ссылки на объекты, переданные как параметры конструктора, или ваш класс имеет константные переменные, то у вас нет выбора, кроме использования списков инициализаторов.
Одной из важных причин использования списка инициализаторов конструктора, который здесь не упоминается, является инициализация базового класса.
As по порядку построения базовый класс должен быть построен до класса ребенка. Без списка инициализатора конструктора это возможно, если ваш базовый класс имеет конструктор по умолчанию, который будет вызываться непосредственно перед вводом конструктора дочернего класса.
Но если ваш базовый класс имеет только параметризованный конструктор, то вы должны использовать конструктор, чтобы убедиться, что ваш базовый класс инициализирован до дочернего класса.
Используя список инициализаторов конструктора, вы инициализируете своих членов данных точным состоянием, которое вам нужно в коде, а не сначала инициализируйте их до состояния по умолчанию и amp; затем измените свое состояние на тот, который вам нужен в вашем коде.
Если нестатические члены данных const в вашем класс имеют стандартные конструкторы & amp; вы не используете список инициализаторов конструктора, вы не сможете их инициализировать до предполагаемого состояния, поскольку они будут инициализированы в их состоянии по умолчанию.
Элементы ссылочных данных должны быть инициализированы, когда компилятор входит в конструктор, поскольку ссылки не могут быть просто объявлены & amp; инициализируется позже. Это возможно только с помощью списка инициализаторов конструктора.