在 C9803 中
在 C++ 98/03 中封裝 OpenGL 物件需要遵守 C++規則 3.這意味著新增複製建構函式,複製賦值運算子和解構函式。
但是,複製建構函式應該在邏輯上覆制該物件。複製 OpenGL 物件是一件非常重要的事情。同樣重要的是,它幾乎肯定是使用者不希望做的事情。
因此,我們將使物件不可複製:
class BufferObject
{
public:
BufferObject(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
{
glGenBuffers(1, &object_);
glBindBuffer(target, object_);
glBufferData(target, size, data, usage);
glBindBuffer(target, 0);
}
~BufferObject()
{
glDeleteBuffers(1, &object_);
}
//Accessors and manipulators
void Bind(GLenum target) const {glBindBuffer(target, object_);}
GLuint GetObject() const {return object_;}
private:
GLuint object_;
//Prototypes, but no implementation.
BufferObject(const BufferObject &);
BufferObject &operator=(const BufferObject &);
};
建構函式將建立物件並初始化緩衝區物件的資料。解構函式將破壞物件。通過宣告覆制建構函式/賦值而不定義它們,如果任何程式碼試圖呼叫它們,連結器將給出錯誤。通過宣稱它們是私有的,只有 BufferObject
的成員甚至可以呼叫他們。
請注意,BufferObject
不會保留傳遞給建構函式的 target
。這是因為 OpenGL 緩衝區物件可以與任何目標一起使用,而不僅僅是最初建立的目標。這與紋理物件不同,紋理物件必須始終繫結到最初建立的目標。
因為 OpenGL 非常依賴於將物件繫結到上下文以用於各種目的,所以具有 RAII 樣式的範圍物件繫結通常也是有用的。因為不同的物件具有不同的繫結需求(一些具有目標,而另一些沒有),我們必須分別為每個物件實現一個。
class BindBuffer
{
public:
BindBuffer(GLenum target, const BufferObject &buff) : target_(target)
{
buff.Bind(target_);
}
~BindBuffer()
{
glBindBuffer(target_, 0);
}
private:
GLenum target_;
//Also non-copyable.
BindBuffer(const BindBuffer &);
BindBuffer &operator=(const BindBuffer &);
};
BindBuffer
是不可複製的,因為複製它是沒有意義的。請注意,它不會保留對它所繫結的 BufferObject
的訪問許可權。那是因為沒必要。