在C ++中,是否可以在构造函数中访问静态变量?

时间:2011-12-03 12:03:47

标签: c++ static constructor

我在尝试:

class MyClass {
public:
    MyClass();

    int myID;
    static int currentID;
};

MyClass::MyClass() {
    myID = currentID;
    ++currentID;
}

我正在尝试为此类的所有实例分配一个唯一ID。

编辑:

它对我不起作用。我在xcode中得到了两个:

未定义的符号:   “GameObject :: currentID”,引自:       GameObject.o中的__ZN10GameObject9currentIDE $ non_lazy_ptr      (也许你的意思是:__ ZN10GameObject9currentIDE $ non_lazy_ptr) ld:找不到符号 collect2:ld返回1退出状态

7 个答案:

答案 0 :(得分:5)

对我有用:

#include <iostream>

class My
{
    public:
    My() : id(++currentId) {}

    int id;
    static int currentId;
};

int My::currentId = 0;

std::ostream & operator<<(std::ostream & os, My & m)
{
    return os << m.id;
}

int main()
{
    My a;
    My b;
    My c;

    std::cout << a << std::endl;
    std::cout << b << std::endl;
    std::cout << c << std::endl;
}

输出:

> ./x
1
2
3

答案 1 :(得分:3)

除了其他案例外,它还适用于以下情况:

MyClass a[10];
MyClass* b = new MyClass[10];

如果使用STL容器来保存MyClass个对象,请务必小心。 可能与您预期的行为不一样,但很难找到问题。请参阅以下示例:

int MyClass::currentID = 0;
...
std::vector<MyClass> c(10);
MyClass a;

在这种情况下,结果如下:

c[0].myID = 0;
c[1].myID = 0;
....
c[9].myID = 0
=============
   a.myID = 1. 

默认构造函数只执行一次。原因是std :: vector的构造函数将使用相同的值来初始化向量的所有元素。在我的系统中,std :: vector的构造函数如下:

  explicit
  vector(size_type __n, const value_type& __value = value_type(),
     const allocator_type& __a = allocator_type())
  : _Base(__n, __a)
  { _M_fill_initialize(__n, __value); }   

_M_fill_initialize将使用__value(来自默认构造函数value_type()__n次来初始化分配的内存。

上面的代码最终将调用uninitialized_fill_n,其执行以下操作:

for (; __n > 0; --__n, ++__cur)
    std::_Construct(&*__cur, __x);

以下是std::_Contruct

template<typename _T1, typename _T2>
inline void
_Construct(_T1* __p, const _T2& __value)
{
  // _GLIBCXX_RESOLVE_LIB_DEFECTS
  // 402. wrong new expression in [some_]allocator::construct
  ::new(static_cast<void*>(__p)) _T1(__value);
}

在这里你可以看到它最终调用全局运算符new来使用相同的值初始化向量中的每个元素。

结论是,使用静态成员到初始数据成员将在大多数情况下工作,但如果您打算在STL容器中使用它,它可能会失败,并且很难找到问题。我只尝试std::vector,当使用其他类型的带有MyClass对象的stl容器时,很可能存在问题。

答案 2 :(得分:1)

您收到错误的原因不是因为您正在从构造函数中访问静态,这是合法的btw,但是因为您没有定义它。

class My
{
    public:
    My() : id(++currentId) {}

    int id;
    static int currentId;
};

//place the definition in the implementation file
int My::currentId = 0;

答案 3 :(得分:0)

是的,没有问题,只要你没有MyClass的静态实例。

答案 4 :(得分:0)

是的,没关系。但是你编写的代码不是线程安全的:可以在不同的线程中同时实例化2个类。在第一个实例有时间增加静态变量之前,第二个实例可以获取currentID的相同值。

这对您来说可能是也可能不是问题。

如果您需要线程安全,this question应该有帮助。

答案 5 :(得分:0)

int MyClass::currentID=0;  

如果没有完成,您需要在CPP文件中执行此操作

答案 6 :(得分:0)

您需要确保在类之外定义和初始化类的静态成员。这对我有用:

#include <iostream>
class MyClass {
private:
    int myID;
    static int currentID;
public:
   //default constructor
    MyClass()
        : myID(currentID) 
        {
            ++currentID;
        }

    void printId() { std::cout << "Object Id :" << myID << std::endl; } /*Prints the unique ID assigned to each object.*/
};

// define the static class member here:
int MyClass::currentID = 1;

int main()
{
    MyClass m1, m2, m3;
    m1.printId();
    m2.printId();
    m3.printId();
}

输出:

对象ID:1

对象ID:2

对象ID:3