статические конструкторы в C++? Я должен инициализировать частные статические объекты

Причина foldl' предпочтена foldl для 99% всего использования, то, что это может работать в постоянном пространстве за большей частью использования.

Берут функцию sum = foldl['] (+) 0. Когда foldl' используется, сумма сразу вычисляется, таким образом применение sum к бесконечному списку будет просто работать навсегда, и скорее всего в постоянном пространстве (если you’re с помощью вещей как Int с, Double с, Float с. Integer с будет использовать больше, чем постоянное пространство, если число станет больше, чем maxBound :: Int).

С [1 110], преобразователь создается (как рецепт того, как получить ответ, который может быть оценен позже, вместо того, чтобы хранить ответ). Эти преобразователи могут поднять много пространства, и в этом случае, it’s намного лучше для оценки выражения, чем сохранить преобразователя (ведущий к стеку overflow… и продвижение Вас to… о, не берите в голову)

Hope, которая помогает.

172
задан peterh says reinstate Monica 14 June 2016 в 04:10
поделиться

9 ответов

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

class StaticStuff
{
     std::vector<char> letters_;

public:
     StaticStuff()
     {
         for (char c = 'a'; c <= 'z'; c++)
             letters_.push_back(c);
     }

     // provide some way to get at letters_
};

class Elsewhere
{
    static StaticStuff staticStuff; // constructor runs once, single instance

};
178
ответ дан 23 November 2019 в 20:39
поделиться

Что ж, у вас может быть

class MyClass
{
    public:
        static vector<char> a;

        static class _init
        {
          public:
            _init() { for(char i='a'; i<='z'; i++) a.push_back(i); }
        } _initializer;
};

Не забудьте (в .cpp) следующее:

vector<char> MyClass::a;
MyClass::_init MyClass::_initializer;

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

80
ответ дан 23 November 2019 в 20:39
поделиться

Как насчет создания шаблона, имитирующего поведение C #.

template<class T> class StaticConstructor
{
    bool m_StaticsInitialised = false;

public:
    typedef void (*StaticCallback)(void);

    StaticConstructor(StaticCallback callback)
    {
        if (m_StaticsInitialised)
            return;

        callback();

        m_StaticsInitialised = true;
    }
}

template<class T> bool StaticConstructor<T>::m_StaticsInitialised;

class Test : public StaticConstructor<Test>
{
    static std::vector<char> letters_;

    static void _Test()
    {
        for (char c = 'a'; c <= 'z'; c++)
            letters_.push_back(c);
    }

public:
    Test() : StaticConstructor<Test>(&_Test)
    {
        // non static stuff
    };
};
0
ответ дан 23 November 2019 в 20:39
поделиться

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

//Foo.h
class Foo
{
 private:
  static int hello;
};


//Foo.cpp
int Foo::hello = 1;
0
ответ дан 23 November 2019 в 20:39
поделиться

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

foo.h

class Foo
{
public:
    void bar();
private:
    static int count;
};

foo.cpp

#include "foo.h"

void Foo::bar()
{
    // method definition
}

int Foo::count = 0;
0
ответ дан 23 November 2019 в 20:39
поделиться

Концепция статических конструкторов была введена в Java после того, как они узнали о проблемах в C ++. Таким образом, у нас нет прямого эквивалента.

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

//header

class A
{
    // Make sure this is private so that nobody can missues the fact that
    // you are overriding std::vector. Just doing it here as a quicky example
    // don't take it as a recomendation for deriving from vector.
    class MyInitedVar: public std::vector<char>
    {
        public:
        MyInitedVar()
        {
           // Pre-Initialize the vector.
           for(char c = 'a';c <= 'z';++c)
           {
               push_back(c);
           }
        }
    };
    static int          count;
    static MyInitedVar  var1;

};


//source
int            A::count = 0;
A::MyInitedVar A::var1;
6
ответ дан 23 November 2019 в 20:39
поделиться

Нет необходимости в init () функция std :: vector может быть создана из диапазона:

// h file:
class MyClass {
    static std::vector<char> alphabet;
// ...
};

// cpp file:
#include <boost/range.hpp>
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
std::vector<char> MyClass::alphabet( boost::begin( ::alphabet ), boost::end( ::alphabet ) );

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

C ++ 11 Обновление

Начиная с C ++ 11, вы можете сделать это вместо этого:

// cpp file:
std::vector<char> MyClass::alphabet = { 'a', 'b', 'c', ..., 'z' };

Это семантически эквивалентно решению C ++ 98 в исходном ответе, но вы не можете использовать строковый литерал справа -сайд, так что не совсем лучше. Однако если у вас есть вектор любого другого типа, кроме char , wchar_t ,

9
ответ дан 23 November 2019 в 20:39
поделиться

В файле .h:

class MyClass {
private:
    static int myValue;
};

В файле .cpp:

#include "myclass.h"

int MyClass::myValue = 0;
19
ответ дан 23 November 2019 в 20:39
поделиться

При попытке скомпилировать и использовать класс Elsewhere (из Earwicker's answer) я получаю:

error LNK2001: unresolved external symbol "private: static class StaticStuff Elsewhere::staticStuff" (?staticStuff@Elsewhere@@0VStaticStuff@@A)

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

Для такой компиляции можно использовать "статический метод со статической локальной переменной внутри". Что-то вроде этого:

class Elsewhere
{
public:
    static StaticStuff& GetStaticStuff()
    {
        static StaticStuff staticStuff; // constructor runs once, single instance
        return staticStuff;
    }
};

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

Уго Гонсалес Кастро.

4
ответ дан 23 November 2019 в 20:39
поделиться
Другие вопросы по тегам:

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