Как инициализировать частные статические члены в C ++? - PullRequest
460 голосов
/ 09 октября 2008

Каков наилучший способ инициализации частного статического члена данных в C ++? Я попробовал это в моем заголовочном файле, но он дает мне странные ошибки компоновщика:

class foo
{
    private:
        static int i;
};

int foo::i = 0;

Я предполагаю, что это потому, что я не могу инициализировать приватного члена извне класса. Так какой же лучший способ сделать это?

Ответы [ 17 ]

4 голосов
/ 31 декабря 2013

Я следую идее Карла. Мне нравится это, и теперь я использую это также. Я немного изменил обозначения и добавил некоторые функции

#include <stdio.h>

class Foo
{
   public:

     int   GetMyStaticValue () const {  return MyStatic();  }
     int & GetMyStaticVar ()         {  return MyStatic();  }
     static bool isMyStatic (int & num) {  return & num == & MyStatic(); }

   private:

      static int & MyStatic ()
      {
         static int mStatic = 7;
         return mStatic;
      }
};

int main (int, char **)
{
   Foo obj;

   printf ("mystatic value %d\n", obj.GetMyStaticValue());
   obj.GetMyStaticVar () = 3;
   printf ("mystatic value %d\n", obj.GetMyStaticValue());

   int valMyS = obj.GetMyStaticVar ();
   int & iPtr1 = obj.GetMyStaticVar ();
   int & iPtr2 = valMyS;

   printf ("is my static %d %d\n", Foo::isMyStatic(iPtr1), Foo::isMyStatic(iPtr2));
}

это выводит

mystatic value 7
mystatic value 3
is my static 1 0
3 голосов
/ 23 мая 2014

А как насчет set_default() метода?

class foo
{
    public:
        static void set_default(int);
    private:
        static int i;
};

void foo::set_default(int x) {
    i = x;
}

Нам нужно будет использовать только метод set_default(int x), и наша переменная static будет инициализирована.

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

3 голосов
/ 26 января 2014

Также работает в файле privateStatic.cpp:

#include <iostream>

using namespace std;

class A
{
private:
  static int v;
};

int A::v = 10; // possible initializing

int main()
{
A a;
//cout << A::v << endl; // no access because of private scope
return 0;
}

// g++ privateStatic.cpp -o privateStatic && ./privateStatic
2 голосов
/ 10 сентября 2017

Возможно, возникла проблема с компоновщиком:

  • Предоставление определения класса и статического члена в заголовочном файле,
  • Включение этого заголовка в два или более исходных файла.

Это распространенная проблема для тех, кто начинает с C ++. Статический член класса должен быть инициализирован в одной единице перевода, т.е. в одном исходном файле.

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

class Foo
{
    // int& getObjectInstance() const {
    static int& getObjectInstance() {
        static int object;
        return object;
    }

    void func() {
        int &object = getValueInstance();
        object += 5;
    }
};
1 голос
/ 14 июня 2018

Один из "старых" способов определения констант состоит в замене их на enum:

class foo
{
    private:
        enum {i = 0}; // default type = int
        enum: int64_t {HUGE = 1000000000000}; // may specify another type
};

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

1 голос
/ 01 октября 2016

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

Мне нужно было инициализировать приватный статический член данных в классе шаблона.

в .h или .hpp выглядит примерно так, чтобы инициализировать член статических данных класса шаблона:

template<typename T>
Type ClassName<T>::dataMemberName = initialValue;
0 голосов
/ 02 сентября 2016

Служит ли это вашей цели?

//header file

struct MyStruct {
public:
    const std::unordered_map<std::string, uint32_t> str_to_int{
        { "a", 1 },
        { "b", 2 },
        ...
        { "z", 26 }
    };
    const std::unordered_map<int , std::string> int_to_str{
        { 1, "a" },
        { 2, "b" },
        ...
        { 26, "z" }
    };
    std::string some_string = "justanotherstring";  
    uint32_t some_int = 42;

    static MyStruct & Singleton() {
        static MyStruct instance;
        return instance;
    }
private:
    MyStruct() {};
};

//Usage in cpp file
int main(){
    std::cout<<MyStruct::Singleton().some_string<<std::endl;
    std::cout<<MyStruct::Singleton().some_int<<std::endl;
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...