C ++: ссылка и вопрос указателя (пример, касающийся OpenGL) - PullRequest
0 голосов
/ 02 января 2011

Я хотел бы загрузить текстуры, а затем использовать их для нескольких объектов. Будет ли это работать?

class Sprite
{
    GLuint* mTextures; // do I need this to also be a reference?

    Sprite( GLuint* textures ) // do I need this to also be a reference?
    {
        mTextures = textures;
    }

    void Draw( textureNumber )
    {
        glBindTexture( GL_TEXTURE_2D, mTextures[ textureNumber ] );
        // drawing code
    }
};

// normally these variables would be inputed, but I did this for simplicity.
const int NUMBER_OF_TEXTURES = 40;
const int WHICH_TEXTURE = 10;

void main()
{
    std::vector<GLuint> the_textures;
    the_textures.resize( NUMBER_OF_TEXTURES );

    glGenTextures( NUMBER_OF_TEXTURES, &the_textures[0] );

    // texture loading code

    Sprite the_sprite( &the_textures[0] );
    the_sprite.Draw( WHICH_TEXTURE );
}

И есть ли другой способ сделать это, даже если это сработает?

Спасибо.

Ответы [ 4 ]

2 голосов
/ 02 января 2011
  1. да, это будет работать
  2. нет необходимости делать их ссылками: вы храните / передаете копию указателя (это быстро), и вы не планируете изменять этот указатель за пределами
  3. Есть много разных способов сделать это, и правильный способ зависит от других требований вашего кода.

например. Вы можете использовать глобальный экземпляр текстур:

textures.cpp:

static std::vector load_once_textures();
std::vector<GLuint> const& get_textures()
{
    static std::vector<GLuint> const the_textures = load_once_textures();
    return the_textures;
}

std::vector load_once_textures()
{
    // loading
}

textures.h

std::vector<GLuint> const& get_textures();

это простой подход и достаточно безопасный, потому что текстуры загружаются один раз, и при загрузке не возникает проблема неоднозначности порядка статической инициализации

2 голосов
/ 02 января 2011

Этот конкретный случай должен работать.Однако, как только "the_textures" выходит из области видимости, указатель, удерживаемый Sprite, становится недействительным.Это было бы то же самое, даже если бы это была ссылка.В этом случае я предлагаю вам вместо этого поместить класс std :: vector <> в класс Sprite, чтобы он принадлежал и управлялся этим экземпляром класса.

0 голосов
/ 02 января 2011

Поскольку идентификатор текстуры не меняется, как насчет использования значения GLuint в Sprite вместо сохранения array-ptr и выбора спрайта для рисования?

Кажется проще и не нужнобеспокоиться о области видимости

Это если вам не нужно вызывать glDeleteTextures перед выходом из приложения, тогда я предлагаю вам создать класс TextureMgr или что-то, что решит эту проблему раз и навсегда.;)

0 голосов
/ 02 января 2011

Мне интересно, почему Draw не может просто взять ссылку на объект, который рисует.

class Sprite
{
public:

    Sprite()
    {
    }

    void Draw( GLuint & texture )
    {
        glBindTexture( GL_TEXTURE_2D, texture );
        // drawing code
    }
};
  • Sprite - это тип, который рисует определенным образом
  • GLuint - это тип, который рисуется

Где-то здесь может быть полиморфизм: - у вас разные алгоритмы розыгрыша - существуют полиморфные (виртуальные) методы в различных типах объектов, которые рисуются

так что Draw может быть виртуальным методом, а GLuint может быть абстрактным базовым классом, и в этом случае фактический вектор будет не с объектами, а с указателями на различные типы объектов.

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

Кстати, main должен возвращать int, а не void.

...