C ++ inicializace statické Stack

hlasů
2

Mám několik otázek týkajících se inicializace statické kolekci. Zde je příklad I kódované, který se zdá k práci:

#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;
}

Nyní je to nejlepší způsob, jak dělat to, co jsem se snaží dosáhnout? Z nějakého důvodu, když se snažím přesně tento stejný režim v mém reálném kód, volat nahoru () vytiskne nesmysly. Mohl by existovat žádný důvod pro to?

Kdyby můj příklad je v pořádku, snad budu uchýlit k odeslání mé skutečné kód.


Zde je skutečný kód:

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();

A protože jsem nemůže dostat kód stohu do práce, jsem se rozhodla pro toto v současné době:

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.);
}

Může někdo odhalit chybu v kódu s komínem, nebo třeba zlepšit na mé narychlo kódované řešení?

Položena 23/04/2009 v 04:25
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
1

Zde je jeden ze způsobů, jak to udělat:

#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;
}
Odpovězeno 10/04/2011 v 15:09
zdroj uživatelem

hlasů
1

Nemyslím si, že kód bude i kompilovat (chybějící A::ze initializeNumbers()pro začátek).

Navrhuji, abyste psát své skutečné kód.

Nicméně, proč ne jen inicializovat zásobník na prvním konstruktoru hovoru (s ochranou vlákna, pokud máte spuštěnou v prostředí s více podprocesy samozřejmě).

To se zdá být mnohem čistší způsob, jak to udělat, něco jako (nevyzkoušený):

#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;
}
Odpovězeno 23/04/2009 v 04:32
zdroj uživatelem

hlasů
0

Jestli se něco v tomto duchu by vám pomoci. I přesto raději Pax je návrh, že je to jednodušší, ale to by se měli vyhnout své „je init“ starosti.

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;

V případě, že dědičnost dělá quesy (což by mělo, to aint dost), jen souhrnnou stack do NumStack. To bude vyžadovat některé změny v užívání čísel v kódu i když:

class NumStack
{
public:
   NumStack(){
      obj.push(42);
   }
   stack<int> obj;
}; 
Odpovězeno 23/04/2009 v 05:32
zdroj uživatelem

hlasů
0

Tam může být určitě důvod. Tam jsou opravdu dva problémy s tímto přístupem obecně. Prvním problémem je, že statické inicializátory spuštěn dříve, než začne hlavní metodou v jazyce C ++. To znamená, že initializeNumbers potrvá, než cokoliv jiného programu. V tomto omezeném vzorku, že to není velký problém.

Druhým problémem však je, že C ++ neposkytuje žádnou záruku na objednání. Což znamená, pokud máte více než jeden staticky inicializované proměnné, kompilátor je zatím jejich inicializovat v libovolném pořadí to potěší. Takže pokud máte závislost na jednom statické proměnné v anothers inicializátor budete narazit na chyby (a vytváří jemnou závislost je velmi snadné dělat).

Jste pravděpodobně mnohem lépe tady dělá nějakou formu zpožděné inicializace pro komplexní statické hodnoty.

Odpovězeno 23/04/2009 v 04:35
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more