Инициализировать статические переменные в классе C++?



Я заметил, что некоторые из моих функций в классе на самом деле не имеют доступа к объекту, поэтому я сделал их static. Затем компилятор сказал мне, что все переменные, к которым они также должны быть статическими – ну, вполне понятно до сих пор. У меня есть куча строковых переменных, таких как



string RE_ANY = "([^n]*)";
string RE_ANY_RELUCTANT = "([^n]*?)";


и так далее в классе. Я тогда сделал их все static const потому что они никогда не меняются. Однако моя программа компилируется только в том случае, если я перемещаю их из класса: в противном случае MSVC++2010 жалуется "Только статические постоянные интегральные переменные могут быть инициализированы в пределах класса".



ну это прискорбно. Есть ли обходной путь? Я хотел бы оставить их внутри класса, которому они принадлежат.

1347   9  

9 ответов:

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

// inside the class
class Thing {
    static string RE_ANY;
    static string RE_ANY_RELUCTANT;
};

// in the source file
string Thing::RE_ANY = "([^\n]*)";
string Thing::RE_ANY_RELUCTANT = "([^\n]*?)";

обновление

Я только что заметил первую строку вашего вопроса-Вы не хочу сделать эти функции static, вы хотите сделать их const. Делая их static означает, что они больше не связаны с объектом (поэтому они не могут получить доступ к каким-либо нестатическим членам), а статичность данных означает это будет совместно использоваться со всеми объектами этого типа. Это вполне может быть не то, что вы хотите. Делая их const просто означает, что они не могут изменить, но все равно можете получить к ним доступ.

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

class Foo
{
    static const int someInt = 1;
    static const short someShort = 2;
    // etc.
};

и вы не можете сделать это с любым другим типом, в этом случае вы должны определить их в своем .файл cpp.

статические переменные-члены должны быть объявлены в классе, а затем определен вне его!

нет обходного пути, просто поместите их фактическое определение в исходный файл.


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

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

Так как C++11 это может быть сделано внутри класса с constexpr.

class stat {
    public:
        // init inside class
        static constexpr double inlineStaticVar = 22;
};

переменная теперь может быть доступна с помощью:

stat::inlineStaticVar

Я чувствую, что стоит добавить, что статическая переменная-это не то же самое, что постоянная переменная.

использование постоянной переменной в классе

struct Foo{
    const int a;
    Foo(int b) : a(b){}
}

и мы объявили бы это как так

fooA = new Foo(5);
fooB = new Foo(10);
// fooA.a = 5;
// fooB.a = 10;

для статической переменной

struct Bar{
    static int a;
    Foo(int b){
        a = b;
    }
}
Bar::a = 0; // set value for a

который используется так

barA = new Bar(5);
barB = new Bar(10);
// barA.a = 10;
// barB.a = 10;
// Bar::a = 10;

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

где, как и в Bar, их только одно значение для Bar:: a независимо от того, сколько экземпляров Bar сделаны. Все они разделяют это значение, вы также можете получить к нему доступ с помощью любых экземпляров Bar. Статическая переменная также соблюдает правила для public / private, поэтому вы можете сделать так, что только экземпляры Bar могут читать значение Bar:: a;

просто добавить поверх других ответов. Для того, чтобы инициализировать сложный статический член!--4-->, вы можете сделать это следующим образом:

объявить статический член, как обычно.

// myClass.h
class myClass
{
static complexClass s_complex;
//...
};

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

//class.cpp    
#include myClass.h
complexClass initFunction()
{
    complexClass c;
    c.add(...);
    c.compute(...);
    c.sort(...);
    // Etc.
    return c;
}

complexClass myClass::s_complex = initFunction();

Если ваша цель-инициализировать статическую переменную в заголовочном файле (вместо a *.cpp-файл, который вам может понадобиться, если вы придерживаетесь идиомы "только заголовок"), то вы можете обойти проблему инициализации с помощью шаблона. Шаблонные статические переменные могут быть инициализированы в заголовке, не вызывая определения нескольких символов.

см. здесь для примера:

инициализация статического члена шаблона класса

при необходимости переместите все ваши константы .cpp файл без декларации .H-файл. Используйте анонимное пространство имен, чтобы сделать их невидимыми за пределами модуля cpp.

// MyClass.cpp

#include "MyClass.h"

// anonymous namespace
namespace
{
    string RE_ANY = "([^\n]*)";
    string RE_ANY_RELUCTANT = "([^\n]*?)";
}

// member function (static or not)
bool MyClass::foo()
{
    // logic that uses constants
    return RE_ANY_RELUCTANT.size() > 0;
}

некоторые ответы кажутся вводит в заблуждение немного.

не нужно

  • присвоить значение статическому объекту при инициализации присваивается значение дополнительно.
  • создать еще один .cpp файл для его инициализации, это можно сделать то же самое только в заголовок.

#ifndef CLASS_A_H
#define CLASS_A_H
#include <string>
class A
{
private:
    static std::string str;
    static int x;
};
// Initialize with no values
std::string A::str;
int A::x;
// Initialize with values
//std::string A::str = "SO!";
//int A::x = 900;
#endif

Comments

    Ничего не найдено.