Как в современном (c++11 и более позднем) объявлять статические переменные в классе и можно ли вообще это делать?
#include
using namespace std;
int main()
{
class Class
{
static const short unsigned id = 1;
static const string name = "Заголовок 1";
public:
static short unsigned getId()
{
return id;
}
static string getName()
{
return name;
}
};
cout<
g++ -Wall -march=native -msse3 -O3 -fomit-frame-pointer -pipe -o "oop" "oop.cpp" (в каталоге: /home/ilya/Downloads/Qt)
oop.cpp: В функции «int main()»:
oop.cpp:10:36: ошибка: локальный класс «class main()::Class» не должен иметь статический элемент данных «const short unsigned int main()::Class::id» [-fpermissive]
static const short unsigned id = 1;
^
oop.cpp:11:30: ошибка: локальный класс «class main()::Class» не должен иметь статический элемент данных «const string main()::Class::name» [-fpermissive]
static const string name = "Заголовок 1";
^~~~~~~~~~~~~~~~~~~~~~
oop.cpp:11:23: ошибка: инициализация внутри класса статического элемента данных «const string main()::Class::name» нелитерального типа
static const string name = "Заголовок 1";
^~~~
oop.cpp:11:30: ошибка: вызов non-constexpr функции «std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [с _CharT = char; _Traits = std::char_traits
И если определять из вне.
#include
using namespace std;
int main()
{
class Class
{
public:
static short unsigned id;
static string name;
};
Class::id = 1;
Class::name = "Заголовок 1";
cout<
g++ -Wall -march=native -msse3 -O3 -fomit-frame-pointer -pipe -o "oop" "oop.cpp" (в каталоге: /home/ilya/Downloads/Qt)
oop.cpp: В функции «int main()»:
oop.cpp:11:25: ошибка: локальный класс «class main()::Class» не должен иметь статический элемент данных «short unsigned int main()::Class::id» [-fpermissive]
static short unsigned id;
^~
oop.cpp:12:17: ошибка: локальный класс «class main()::Class» не должен иметь статический элемент данных «std::__cxx11::string main()::Class::name» [-fpermissive]
static string name;
^~~~
Сборка завершилась с ошибкой.
Почему так происходит и что я делаю не так?
Ответ
Обратите внимание на ошибку. Там упоминается, что класс локальный.
#include
class Class
{
public:
static const int id; // можно инициализировать тут
static const std::string name; // нельзя инициализировать тут
};
const int Class::id{111};
const std::string Class::name = "rectangle";
int main()
{
std::cout << Class::id << ' ' << Class::name << std::endl;
return 0;
}
Можно убрать константность, инициализация от этого не пострадает
#include
class Class
{
public:
static int id;
static std::string name;
};
int Class::id{111};
std::string Class::name = "rectangle";
int main()
{
Class c;
std::cout << c.id << ' ' << c.name << std::endl;
return 0;
}
Во втором примере можно обращаться по имени класса и далее через ::, я просто привел для примера через экземпляр и Также рекомендую обратить внимание на фигурную инициализацию, через {}, как сделал для id, она имеет ряд преимуществ, но иногда стоит быть осторожнее, потому что из нее получается объект std::initializer_list. Что касается инициализации внутри класса, то это возможно, если мы имеем статическую константу и интегральный тип:
class Curious
{
static const int c1 = 7; // правильно, но помните об определении
static int c2 = 11; // ошибка: не константа
const int c3 = 13; // ошибка: не статическая константа
static const int c4 = f(17); // ошибка: инициализатор не константа
static const float c5 = 7.0; // ошибка: не интегральный тип
// ...
};
Если (и только если) Вы используете инициализированный член таким образом, что требуется хранить его в памяти, как объект, член должен быть где-нибудь (один раз) определен. Инициализатор не может повторяться:
const int Curious::c1; // это определение, но не повторяйте здесь инициализатор
const int *p = &Curious::c1; // правильно: Curious::c1 был определен
Комментариев нет:
Отправить комментарий