Как Вы вызываете конструктора для глобальных объектов для массивов объектов, и для объектов в классах/структурах?

Если вы ищете другой запрос, отличный от вышеуказанного ответа ...

select a.* from items a join categories b on a.category_id=b.id and b.type='commercial' and a.is_payment=1
union all
select a.* from items a join categories b on a.category_id=b.id and b.type<>'commercial';
12
задан Jeremy Ruten 16 November 2008 в 19:32
поделиться

7 ответов

Глобальные объекты

Ваш - единственный путь. С другой стороны, старайтесь избегать этого. Лучше использовать функции (или даже другие объекты) как фабрики вместо этого. Тем путем можно управлять временем создания.

Массивы объектов

Нет никакого способа сделать это непосредственно. Объекты неPOD будут всегда создаваться из значения по умолчанию. std::fill часто большая справка. Вы могли бы также хотеть изучить средства выделения и std::uninitialized_fill.

Объекты содержатся в классах/структурах

Используйте списки инициализации в своем конструкторе:

class Bar {
    Foo foo;

    Bar() : foo(3) { }
};

Статические участники должны на самом деле быть определены вне класса:

class Bar {
    static Foo foo;
};

Foo Bar::foo(3);
11
ответ дан 2 December 2019 в 18:22
поделиться

Ответ Konrad в порядке, просто puntualization о массивах.... Существует способ создать массив объектов (не указатели), и здесь он следует:

//allocate raw memory for our array
void *rawMemory = operator new[](30 * sizeof(Foo))

// point array_of_foos to this memory so we can use it as an array of Foo
Foo *array_of_foos = static_cast<Foo *>(rawMemory);

// and now we can create the array of objects(NOT pointers to the objects)
//  using the buffered new operator
for (int i = 0; i < 30; i++)
    new(array_of_foos[i])Foo(3);

Этот подход описан здесь: http://www.amazon.com/gp/product/0321334876?ie=UTF8&tag=aristeia.com-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0321334876

3
ответ дан 2 December 2019 в 18:22
поделиться

Исправлять некоторые неправильные представления о globals:

  • Порядок четко определен в единице компиляции.
    • Это совпадает с порядком определения
  • Порядок через единицы компиляции не определен.
  • Порядком разрушения является Полная противоположность создания.

Не что-то я рекомендую, но: Таким образом, простое решение состоит в том, чтобы быть поместить весь globals в единственную единицу компиляции.

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

Foo& getGlobalA() // passed parameters can be passed to constructor
{
    static Foo  A;
    return A;
}
Foo& getGlobalB()
{
    static Foo  B;
    return B;
}
etc. 
4
ответ дан 2 December 2019 в 18:22
поделиться

Для глобального случая нет никакого способа управлять, когда это называют. Спецификация C++ по существу говорит, что это назовут прежде основным () и уничтожат когда-то впоследствии. Кроме этого' компилятор является бесплатным сделать, как ему нравится.

В первом случае массива Вы создаете статический массив объектов Foo. По умолчанию каждое значение в массиве будет инициализировано с конструктором по умолчанию Foo (). Нет никакого пути с необработанным массивом C++, чтобы вынудить конкретного перегруженного конструктора быть вызванным. Можно вывести немного управления путем переключения на вектор вместо массива. У векторного конструктора есть перегруженный вектор конструктора (размер, defaultValue), который должен достигнуть того, что Вы ищете. Но в этом случае необходимо быть осторожными, потому что вместо того, чтобы звонить Foo (3) это позвонит Foo (константа Foo& другой), где другой Foo (3).

Второй случай массива очень похож на первый случай. Единственная реальная разница - то, где память выделяется (на "куче" вместо стека). Это имеет то же ограничение относительно вызова конструктору.

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

class Bar{
  Foo foo;
  Bar() : foo(3){}
};
1
ответ дан 2 December 2019 в 18:22
поделиться

Кажется, существует общая суть в этом потоке, что Вы не можете инициализировать членов массива кроме использования конструктора по умолчанию. Один ответ даже создает другой тип, только для вызова другого конструктора. Даже при том, что Вы можете (если массив не является частью как членом класса!):

struct foo {
    foo(int a): a(a) { }
    explicit foo(std::string s): s(s) { }
private:
    int a;
    std::string s;
};

/* global */
foo f[] = { foo("global"), foo("array") };

int main() {
    /* local */
    foo f[] = { 10, 20, 30, foo("a"), foo("b") };
}

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

Для массивов как участники в классах лучше использовать контейнеры в настоящее время:

struct bar {
    /* create a vector of 100 foo's, initialized with "initial" */
    bar(): f(100, foo("initial")) { }
private:
    std::vector<foo> f;
};

Используя placement-new техника, описанная andy.gurin, является опцией также. Но обратите внимание, что это усложнит вещи. Необходимо будет назвать деструкторы сами. И если какой-либо конструктор бросает, в то время как Вы все еще создаете массив, затем необходимо изобразить, где Вы остановились... В целом, если Вы хотите иметь массивы в своем классе и хотеть инициализировать их, использование a std::vector простая ставка.

1
ответ дан 2 December 2019 в 18:22
поделиться

Конструкция массивов объектов:

Можно изменить исходный пример при помощи параметров по умолчанию.

В настоящее время только конструктор по умолчанию поддерживается.
Это - что-то, что обращается следующей версией (потому что все задают этот вопрос),

0
ответ дан 2 December 2019 в 18:22
поделиться

C++ 0X списки инициализатора решает эту проблему для массивов случая объектов. См. эту запись в блоге Herb Sutter, где он описывает их подробно.

Тем временем Вы смогли работать вокруг проблемы как так:

class Foo {
public:
    Foo(int a) : b(a) {}

private:
    int b;
};

class Foo_3 : public Foo {
public:
    Foo_3() : Foo(3) {}
};

Foo_3 array_of_foos[30];

Здесь, Foo_3 класс существует только в целях вызова Foo конструктор с корректным аргументом. Вы могли сделать это шаблоном даже:

template <int i>    
class Foo_n : public Foo {
public:
    Foo_n() : Foo(i) {}
};

Foo_n<3> array_of_foos[30];

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

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

0
ответ дан 2 December 2019 в 18:22
поделиться
Другие вопросы по тегам:

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