我正在用cpp做一个项目,并且在设计类时遇到一个问题。 我的类名为“ Uniform”,它的模板类型为T,它有一个构造函数,一个析构函数和一个名为“ Bind”的函数,该函数对Shader类型的对象进行引用并返回void。它也很重要,但我认为这并不重要。我想根据T调用一个不同的绑定方法,专门。
我已经尝试为etch Uniform定义一个新的专用模板化类(在本例中为3),但是它对结果不满意,因为这会创建代码重复。我还尝试根据绑定模板链接绑定,这给了我一个链接错误,如下例:
//This is giving link errors
#define I_UNIFORM_CONSTRUCT(x) Uniform(std::string name, x * data , unsigned int count)\
: IUniform(name, count),data(data) {}
class IUniform {
public:
std::string name;
unsigned int count;
IUniform(std::string name , unsigned int count ) {
this->name = name;
this->count = count;}
virtual void Bind(Shader & shader) {};
};
template <class T> class Uniform : public IUniform{
public:
T * data;
I_UNIFORM_CONSTRUCT(T)
void Bind(Shader & shader);
~Uniform()
{
delete[] this->data,sizeof(T)*count;
}
};
template <class T> void Uniform<T>::Bind(Shader & shader) {
std::cout << "Error unsupported uniform" << std::endl;
}
template <> void Uniform<float>::Bind(Shader & shader) {
if (this->count == 4)shader.SetUniform4f(this->name, *(glm::vec4*)this->data);
else if (this->count == 1)shader.SetUniform1f(this->name, *(float*)this->data);
}
template <> void Uniform<glm::mat4>::Bind(Shader & shader) {
if (this->count == 1)shader.SetUniformMat4f(this->name, *(glm::mat4*)this->data);
}
template <> void Uniform<int>::Bind(Shader & shader) {
if (this->count == 1)shader.SetUniform1i(this->name, *(int*)this->data);
}
还有我将要删除的第二个工作示例:
#define I_UNIFORM_CONSTRUCT(x) Uniform(std::string name, x * data , unsigned int count)\
: IUniform(name, count),data(data) {}
class IUniform {
public:
std::string name;
unsigned int count;
IUniform(std::string name , unsigned int count ) {
this->name = name;
this->count = count;}
virtual void Bind(Shader & shader) {};
};
template <class T> class Uniform : public IUniform{
public:
T * data;
I_UNIFORM_CONSTRUCT(T)
void Bind(Shader & shader)override {
std::cout << "Error unsupported uniform" << std::endl;
}
~Uniform()
{
delete[] this->data,sizeof(T)*count;
}
};
template <> class Uniform<float> : public IUniform {
public:
float * data;
I_UNIFORM_CONSTRUCT(float)
void Bind(Shader & shader)override {
if (this->count == 4)shader.SetUniform4f(this->name, *(glm::vec4*)this->data);
else if (this->count == 1)shader.SetUniform1f(this->name, *(float*)this->data);}
~Uniform()
{
delete[] this->data, sizeof(float)*count;
}
};
template <> class Uniform<glm::mat4> : public IUniform {
public:
glm::mat4 * data;
I_UNIFORM_CONSTRUCT(glm::mat4)
void Bind(Shader & shader)override {
if (this->count == 1)shader.SetUniformMat4f(this->name, *(glm::mat4*)this->data);}
~Uniform()
{
delete[] this->data, sizeof(glm::mat4)*count;
}
};
template <> class Uniform<int> : public IUniform {
public:
int * data;
I_UNIFORM_CONSTRUCT(int)
void Bind(Shader & shader)override {
if (this->count == 1)shader.SetUniform1i(this->name, *(int*)this->data);}
~Uniform()
{
delete[] this->data, sizeof(int)*count;
}
};//Too ugly
我希望第一个示例根据T的类型调用专门的Bind,但目前它不链接。说我无法多次定义绑定... 任何人都可以帮助我解决第一个示例或使第二个示例更具可读性吗?
答案 0 :(得分:0)
为阐明我们在评论中的解释,
提供具有相同名称的重载,这些重载可以调用Shader
方法:
void SetUniform(Shader& shader, const std::string& name, glm::vec4& data)
{
shader.SetUniform4f(name, data);
}
void SetUniform(Shader& shader, const std::string& name, float& data)
{
shader.SetUniform1f(name, data);
}
void SetUniform(Shader& shader, const std::string& name, glm::mat4& data)
{
shader.SetUniformMat4f(name, data);
}
void SetUniform(Shader& shader, const std::string& name, int& data)
{
shader.SetUniform1i(name, data);
}
然后
class IUniform
{
public:
std::string name;
IUniform(const std::string& name) : name(name) {}
virtual ~IUniform() = default;
virtual void Bind(Shader&) = 0;
};
template <class T> class Uniform : public IUniform{
public:
T data;
Uniform(const std::string& name, const T& data) : IUniform(name), data(data) {}
void Bind(Shader& shader) override { SetUniform(shader, name, data);}
};
最后,您可以使用Uniform<glm::mat4>
,Uniform<glm::vec4>
,Uniform<float>
,Uniform<int>
。