Страницы

Поиск по вопросам

четверг, 18 апреля 2019 г.

Статические переменные и методы класса

Как в современном (c++11 и более позднем) объявлять статические переменные в классе и можно ли вообще это делать?
#include #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; _Alloc = std::allocator]» static const string name = "Заголовок 1"; ^~~~~~~~~~~~~~~~~~~~~~ Сборка завершилась с ошибкой.
И если определять из вне.
#include #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 #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 #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 был определен

Комментариев нет:

Отправить комментарий