我对初始化静态集合有一些疑问。这是我编码的一个例子似乎有效:
#include <stack>
#include <iostream>
using namespace std;
class A
{
private:
static stack<int> numbers;
static stack<int> initializeNumbers();
public:
A();
};
A::A() { cout << numbers.top() << endl; }
stack<int> A::initializeNumbers()
{
stack<int> numbers;
numbers.push(42);
return numbers;
}
stack<int> A::numbers = initializeNumbers();
int main()
{
A a;
}
现在,这是我想要完成的最佳方式吗?出于某种原因,当我在我的实际代码中尝试这个完全相同的方案时,调用 top()会打印出乱码。这有什么理由吗?
如果我的例子没问题,也许我会求助于发布我的真实代码。
这是真正的代码:
Light.h
#ifndef LIGHT_H_
#define LIGHT_H_
#include <stack>
#include "Vector4.h"
class Light
{
private:
static stack<GLenum> availableLights;
static stack<GLenum> initializeAvailableLights();
public:
GLenum lightID;
Vector4 ambient, diffuse, specular, position, spotDirection;
GLfloat constantAttenuation, linearAttenuation, quadraticAttenuation, spotExponent, spotCutoff;
Light( const Vector4& ambient = Vector4(0.0, 0.0, 0.0, 1.0),
const Vector4& diffuse = Vector4(1.0, 1.0, 1.0, 1.0),
const Vector4& specular = Vector4(1.0, 1.0, 1.0, 1.0),
const Vector4& position = Vector4(0.0, 0.0, 1.0, 0.0),
const Vector4& spotDirection = Vector4(0.0, 0.0, -1.0, 0.0),
GLfloat constantAttenuation = 1.0,
GLfloat linearAttenuation = 0.0,
GLfloat quadraticAttenuation = 0.0,
GLfloat spotExponent = 0.0,
GLfloat spotCutoff = 180.0);
~Light();
};
#endif /*LIGHT_H_*/
Light.cpp
#include <stdexcept> // runtime_error
#include <iostream>
using namespace std;
#include "Light.h"
Light::Light( const Vector4& ambient,
const Vector4& diffuse,
const Vector4& specular,
const Vector4& position,
const Vector4& spotDirection,
GLfloat constantAttenuation,
GLfloat linearAttenuation,
GLfloat quadraticAttenuation,
GLfloat spotExponent,
GLfloat spotCutoff) :
ambient(ambient),
diffuse(diffuse),
specular(specular),
position(position),
spotDirection(spotDirection),
constantAttenuation(constantAttenuation),
linearAttenuation(linearAttenuation),
quadraticAttenuation(quadraticAttenuation),
spotExponent(spotExponent),
spotCutoff(spotCutoff)
{
// This prints gibberish.
cout << availableLights.size() << endl;
// The error is indeed thrown.
if(availableLights.empty())
throw runtime_error("The are no more available light identifiers.");
else
{
lightID = availableLights.top();
availableLights.pop();
}
}
Light::~Light() { availableLights.push(this -> lightID); }
stack<GLenum> Light::initializeAvailableLights()
{
stack<GLenum> availableLights;
availableLights.push(GL_LIGHT7);
availableLights.push(GL_LIGHT6);
availableLights.push(GL_LIGHT5);
availableLights.push(GL_LIGHT4);
availableLights.push(GL_LIGHT3);
availableLights.push(GL_LIGHT2);
availableLights.push(GL_LIGHT1);
availableLights.push(GL_LIGHT0);
return availableLights;
}
stack<GLenum> Light::availableLights = initializeAvailableLights();
由于我无法使用堆栈的代码工作,我现在选择了这个:
Light.h
#ifndef LIGHT_H_
#define LIGHT_H_
#include <stack>
#include "Vector4.h"
class Light
{
private:
static const unsigned int LIGHTS = 9;
static bool availableLights[];
static GLenum lights[];
static GLenum getAvailableLight();
public:
GLenum lightID;
Vector4 ambient, diffuse, specular, position, spotDirection;
GLfloat constantAttenuation, linearAttenuation, quadraticAttenuation, spotExponent, spotCutoff;
Light( const Vector4& ambient = Vector4(0.0, 0.0, 0.0, 1.0),
const Vector4& diffuse = Vector4(1.0, 1.0, 1.0, 1.0),
const Vector4& specular = Vector4(1.0, 1.0, 1.0, 1.0),
const Vector4& position = Vector4(0.0, 0.0, 1.0, 0.0),
const Vector4& spotDirection = Vector4(0.0, 0.0, -1.0, 0.0),
GLfloat constantAttenuation = 1.0,
GLfloat linearAttenuation = 0.0,
GLfloat quadraticAttenuation = 0.0,
GLfloat spotExponent = 0.0,
GLfloat spotCutoff = 180.0);
~Light();
};
#endif /*LIGHT_H_*/
Light.cpp
#include <stdexcept> // runtime_error
#include "Light.h"
Light::Light( const Vector4& ambient,
const Vector4& diffuse,
const Vector4& specular,
const Vector4& position,
const Vector4& spotDirection,
GLfloat constantAttenuation,
GLfloat linearAttenuation,
GLfloat quadraticAttenuation,
GLfloat spotExponent,
GLfloat spotCutoff) :
ambient(ambient),
diffuse(diffuse),
specular(specular),
position(position),
spotDirection(spotDirection),
constantAttenuation(constantAttenuation),
linearAttenuation(linearAttenuation),
quadraticAttenuation(quadraticAttenuation),
spotExponent(spotExponent),
spotCutoff(spotCutoff)
{
lightID = getAvailableLight();
}
Light::~Light()
{
for(unsigned int i = 0; i < LIGHTS; i++)
if(lights[i] == lightID)
availableLights[i] = true;
}
bool Light::availableLights[] = {true, true, true, true, true, true, true, true};
GLenum Light::lights[] = {GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, GL_LIGHT3, GL_LIGHT4, GL_LIGHT5, GL_LIGHT6, GL_LIGHT7};
GLenum Light::getAvailableLight()
{
for(unsigned int i = 0; i < LIGHTS; i++)
if(availableLights[i])
{
availableLights[i] = false;
return lights[i];
}
throw runtime_error("The are no more available light identifiers.");
}
任何人都可以在堆栈代码中发现错误,或者改进我的仓促编码解决方法吗?
答案 0 :(得分:1)
我认为代码甚至不会编译(从A::
开始缺少initializeNumbers()
)。
我建议您发布真实的代码。
但是,为什么不只是在第一个构造函数调用上初始化堆栈(如果你当然在多线程环境中运行,则使用线程保护)。
这似乎是一种更清洁的方式,类似于(未经测试):
#include <stack>
#include <iostream>
using namespace std;
class A {
private:
static boolean isInited = false;
static stack<int> numbers;
public:
A();
};
A::A() {
if (!isInited) {
numbers.push(42);
isInited = true;
}
cout << numbers.top() << endl; }
int main() {
A a;
}
答案 1 :(得分:1)
这是一种方法:
#include <stack>
class C {
static std::stack< C* > c_stack;
static std::stack< C* > getCStack();
};
std::stack< C* > C::c_stack = C::getCStack();
std::stack< C* > C::getCStack() {
std::stack< C* >* c_stack = new std::stack< C* >();
c_stack->push( new C());
return *c_stack;
}
答案 2 :(得分:0)
这绝对是有原因的。这种方法通常有两个问题。第一个问题是静态初始化器在main方法在C ++中启动之前运行。这意味着initializeNumbers将在程序中的任何其他内容之前运行。在这个有限的样本中,这不是什么大问题。
第二个问题是C ++没有为订购提供任何保证。这意味着如果您有多个静态初始化变量,编译器可以按照它喜欢的顺序自由地初始化它们。因此,如果您在其他初始化程序中依赖于一个静态变量,那么您将遇到错误(并且很容易创建一个微妙的依赖项)。
在这里为复杂的静态值进行某种形式的延迟初始化可能会好得多。
答案 3 :(得分:0)
想知道这些方面的内容是否会对你有所帮助。我仍然更喜欢Pax的建议,它更简单,但这应该避免你的“初始化”担忧。
class NumStack : public stack<int>
{
public:
NumStack(){
push(42);
}
};
class A
{
private:
static NumStack numbers;
public:
A();
};
//in cpp file, do as usual for static members
NumStack A::Numbers;
如果继承使你有问题(它应该,它不是很漂亮),只需将堆栈聚合到NumStack中。这需要对代码中数字的使用进行一些更改,但是:
class NumStack
{
public:
NumStack(){
obj.push(42);
}
stack<int> obj;
};