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

В C ++ возможно использовать член данных класса, не определяя объект этого класса, определяя этот член данных в открытом разделе как static переменная, как в примере кода ниже. Вопрос в том, почему / когда я хочу это сделать? и как я могу это сделать?

class ttime{
public:
ttime(int h=0, int m=0, int s=0):hour(h), minute(m), second(s){}   //constructor with default intialization
int& warning(){return hour;}
void display()const{cout<<hour<<"\t";}
static int hello;
~ttime(){}

private:
int hour;
int minute;
int second;
};main()
{
ttime:: hello=11310; //Is this the way to use hello without creating an object of the class?
cout << ttime:: hello;

ttime hi(9);
hi.display();
hi.warning()++;//the user is able to modify your class's private data, which is really bad! You should not be doing this!
hi.display();
}

1

Решение

Как упоминалось ранее, статические переменные-члены работают как «глобальные» переменные, но в пространстве имен класса.
Так что это полезно для счетчиков или общих ресурсов между объектами.

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

Например, входная библиотека может иметь:

class KeyEvent
{
public:
static const int KEY_DOWN = 111;
static const int KEY_UP = 112;
...
}

//And then in your code
#include <KeyEvent>

void poolEvent(Key *key)
{
if(key->type() == KeyEvent::KEY_DOWN)
...
}
1

Другие решения

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

Объявив это public делает его доступным для всех пользователей этого класса. Однако, как правило, плохая идея разрешать изменение переменных класса функциями вне класса.

Объявив это constс другой стороны, это обычный способ предоставления общедоступных констант для класса.

пример

Ваш библиотечный класс:

class Foo
{
public:
// Version number of this code
static const int    VERSION = 1;

private:
// Counts the number of active Foo objects
static int          counter = 0;

public:
// Constructor
Foo()
{
counter++;     // Bump the instance counter
...
}

// Destructor
~Foo()
{
counter--;     // Adjust the counter
...
}
};

Какой-то клиент вашей библиотеки:

class Bar
{
public:
// Constructor
Bar()
{
// Check the Foo library version
if (Foo::VERSION > 1)
std::cerr << "Wrong version of class Foo, need version 1";
...
}
};

В этом примере VERSION является статической константой класса, которая в этом случае сообщает внешнему миру, какая версия кода содержится в классе. Это доступно по синтаксису Foo::VERSION,

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

2

Я не знаком с синтаксисом c ++ для статики в настоящее время. Но в c ++ — cli (.net, Visual C ++) :: верно.
Для статики:
Есть много случаев, когда имеет смысл использовать их. В общем, когда вы хотите хранить информацию, которая принадлежит самому классу (имеется в виду всем объектам класса), а не одному объекту / экземпляру.

1

Несмотря на то, что изначально не был изобретен для этой цели, static constexpr члены данных structs являются основой шаблонного метапрограммирования. Просто проверьте limits Стандартный заголовок библиотеки в качестве простого примера.

Например, мы можем определить обертку вокруг встроенного sizeof оператор. Будучи довольно бесполезным сам по себе, он, надеюсь, дает правильную идею.

#include <iostream>

template<typename T>
struct Calipers
{
static constexpr auto size = sizeof(T);
};

int
main()
{
std::cout << "short:   " << Calipers<short>::size   << "\n";
std::cout << "int:     " << Calipers<int>::size     << "\n";
std::cout << "long:    " << Calipers<long>::size    << "\n";
std::cout << "float:   " << Calipers<float>::size   << "\n";
std::cout << "double:  " << Calipers<double>::size  << "\n";
}

Возможный вывод:

short:   2
int:     4
long:    8
float:   4
double:  8
1

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

Вы найдете это в коде C ++, который был написан до того, как были введены пространства имен, или в метапрограммировании шаблонов, где это более полезно.

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

0