将 2 个未定义类型的参数传递给构造函数(预期为 2 个)
passing 2 parameters of undefined type to a constructor (of 2 expected)
我有一个构造函数,其中我想传递前 2 个参数:
ID3D11ShaderResourceView* 作为稳定下载的纹理 OR
const CHAR* 作为文件名来降低这个纹理并将其分配给 class ID3D11ShaderResourceView* 成员(按需发布以下版本),但我无法理解我应该采用的方式正确地做。它看起来是这样的:
class {button
public
button() {};
button(data1 (or texture or filname), data2 (or texture or filname), rest data....);
...
~button();
}
所以我尝试了:
- 模板失败,可能是知识匮乏的原因,模板
定义一种类型,而我需要选择 2. Varradic 模板,或者我没有正确选择它们,但当我首先只需要区分 2 个时,它们意味着不确定的变量数量。
- 联合,但它与 class 变量集有冲突 - 表示无法将 const char [amount] 与 const char* 匹配,并且联合不适用于 std::string.
- 用 typeid.name() 尝试过 void* 但它总是显示 "void *"
我不想重载构造函数,因为这将创建 4 个以上的构造函数,它们之间几乎没有区别。你认为 boost::variant 在这种情况下对我有帮助吗?是否有任何流畅有效的方法来构建这种构造函数?我的 C++ 知识处于初级水平,抱歉,如果它是一个重复的主题,请阅读它在创建它时向我建议的所有内容,但似乎没有发现任何非常相似的东西,谢谢:)
更新:
已申请 boost::any,得到下一个结果:
class button : public frame {
public:
button() {};
button(boost::any _texture,
boost::any _hover_texture,
...
};
if (_texture.type() == typeid(ID3D11ShaderResourceView*)) texture = boost::any_cast<ID3D11ShaderResourceView*>(_texture);
if (_texture.type() == typeid(const char*))
{
if ( FAILED(D3DX11CreateShaderResourceViewFromFile(gvDevice,boost::any_cast<const char*>(_texture), NULL, NULL, &texture, NULL )) )
mboxout( "loading texture failed.", "UI texture load error", true );
};
if (_hover_texture.type() == typeid(ID3D11ShaderResourceView*)) hover_texture = boost::any_cast<ID3D11ShaderResourceView*>(_hover_texture);
if (_hover_texture.type() == typeid(const char*))
{
if ( FAILED(D3DX11CreateShaderResourceViewFromFile(gvDevice, boost::any_cast<const char*>(_hover_texture), NULL, NULL, &hover_texture, NULL )) )
mboxout( "loading texture failed.", "UI texture load error", true );
};
这是唯一可能的决定吗,因为这个对我来说似乎很尴尬?谢谢:)
一如既往,当您有组合 explosion/tedious 重复时,将您的代码重构为可重用的单元.
在这种情况下,您的构造函数可能只是
template <typename T1, typename T2>
button(T1 const& texture, T2 const& hover_texture)
: _texture(load(texture)),
_hover_texture(load(hover_texture))
{
};
所有的加载逻辑都在里面……你猜是 load
函数。一个示例实现:
static ID3D11ShaderResourceView* load(ID3D11ShaderResourceView* v){
return v; // just return the resources passed in
}
static ID3D11ShaderResourceView* load(char const* fname) {
ID3D11ShaderResourceView* p = NULL;
if (FAILED(D3DX11CreateShaderResourceViewFromFile(gvDevice, fname, NULL, NULL, &p, NULL)))
throw std::runtime_error(std::string("loading texture failed (") + fname + ")");
return p;
}
Note: while we were at it we separated UI from business logic. You do not want to display messageboxes from inside constructors. Ever. You just want to notify the caller of the problem and the caller decides what to do (use another resource, try a different path, retry a download, write a warning message to the log, shut down etc.)
完整演示
#include <iostream>
#include <stdexcept>
///////////////////////////////////////////////////////
// mocking ID3D*
struct ID3D11ShaderResourceView;
enum ERROR_CODE { ERR_OK };
#define FAILED(e) (ERR_OK != (e))
static int gvDevice = 42;
ERROR_CODE D3DX11CreateShaderResourceViewFromFile(int, char const* fname, void*, void*, ID3D11ShaderResourceView**, void*) {
std::cout << "Loaded from " << fname << "\n";
return ERR_OK;
}
//
///////////////////////////////////////////////////////
struct frame{ virtual ~frame() = default; };
class button : public frame {
public:
button() {};
template <typename T1, typename T2>
button(T1 const& texture, T2 const& hover_texture)
: _texture(load(texture)),
_hover_texture(load(hover_texture))
{
};
private:
// TODO Rule-Of-Three constructor/destructorl
// SUGGEST: Rule-Of-Zero using shared pointers instead
ID3D11ShaderResourceView* _texture;
ID3D11ShaderResourceView* _hover_texture;
static ID3D11ShaderResourceView* load(ID3D11ShaderResourceView* v) { return v; }
static ID3D11ShaderResourceView* load(char const* fname) {
ID3D11ShaderResourceView* p = NULL;
if (FAILED(D3DX11CreateShaderResourceViewFromFile(gvDevice, fname, NULL, NULL, &p, NULL)))
throw std::runtime_error(std::string("loading texture failed (") + fname + ")");
return p;
}
};
#include <cassert>
int main() {
ID3D11ShaderResourceView* default_texture = NULL;
assert(!FAILED( D3DX11CreateShaderResourceViewFromFile(gvDevice, "default_texture.bin", NULL, NULL, &default_texture, NULL)));
try {
button button1("t1.bin", "hover1.bin");
button button2(default_texture, "hover2.bin");
button button3("t3.bin", default_texture);
button button4(default_texture, default_texture);
} catch(std::exception const& e) {
std::cout << "Oops: " << e.what() << "\n";
}
}
打印:
Loaded from default_texture.bin
Loaded from t1.bin
Loaded from hover1.bin
Loaded from hover2.bin
Loaded from t3.bin
还有很多需要改进的地方(例如,请参阅评论)但这是一个开始。
我有一个构造函数,其中我想传递前 2 个参数: ID3D11ShaderResourceView* 作为稳定下载的纹理 OR const CHAR* 作为文件名来降低这个纹理并将其分配给 class ID3D11ShaderResourceView* 成员(按需发布以下版本),但我无法理解我应该采用的方式正确地做。它看起来是这样的:
class {button
public
button() {};
button(data1 (or texture or filname), data2 (or texture or filname), rest data....);
...
~button();
}
所以我尝试了:
- 模板失败,可能是知识匮乏的原因,模板 定义一种类型,而我需要选择 2. Varradic 模板,或者我没有正确选择它们,但当我首先只需要区分 2 个时,它们意味着不确定的变量数量。
- 联合,但它与 class 变量集有冲突 - 表示无法将 const char [amount] 与 const char* 匹配,并且联合不适用于 std::string.
- 用 typeid.name() 尝试过 void* 但它总是显示 "void *"
我不想重载构造函数,因为这将创建 4 个以上的构造函数,它们之间几乎没有区别。你认为 boost::variant 在这种情况下对我有帮助吗?是否有任何流畅有效的方法来构建这种构造函数?我的 C++ 知识处于初级水平,抱歉,如果它是一个重复的主题,请阅读它在创建它时向我建议的所有内容,但似乎没有发现任何非常相似的东西,谢谢:)
更新: 已申请 boost::any,得到下一个结果:
class button : public frame {
public:
button() {};
button(boost::any _texture,
boost::any _hover_texture,
...
};
if (_texture.type() == typeid(ID3D11ShaderResourceView*)) texture = boost::any_cast<ID3D11ShaderResourceView*>(_texture);
if (_texture.type() == typeid(const char*))
{
if ( FAILED(D3DX11CreateShaderResourceViewFromFile(gvDevice,boost::any_cast<const char*>(_texture), NULL, NULL, &texture, NULL )) )
mboxout( "loading texture failed.", "UI texture load error", true );
};
if (_hover_texture.type() == typeid(ID3D11ShaderResourceView*)) hover_texture = boost::any_cast<ID3D11ShaderResourceView*>(_hover_texture);
if (_hover_texture.type() == typeid(const char*))
{
if ( FAILED(D3DX11CreateShaderResourceViewFromFile(gvDevice, boost::any_cast<const char*>(_hover_texture), NULL, NULL, &hover_texture, NULL )) )
mboxout( "loading texture failed.", "UI texture load error", true );
};
这是唯一可能的决定吗,因为这个对我来说似乎很尴尬?谢谢:)
一如既往,当您有组合 explosion/tedious 重复时,将您的代码重构为可重用的单元.
在这种情况下,您的构造函数可能只是
template <typename T1, typename T2>
button(T1 const& texture, T2 const& hover_texture)
: _texture(load(texture)),
_hover_texture(load(hover_texture))
{
};
所有的加载逻辑都在里面……你猜是 load
函数。一个示例实现:
static ID3D11ShaderResourceView* load(ID3D11ShaderResourceView* v){
return v; // just return the resources passed in
}
static ID3D11ShaderResourceView* load(char const* fname) {
ID3D11ShaderResourceView* p = NULL;
if (FAILED(D3DX11CreateShaderResourceViewFromFile(gvDevice, fname, NULL, NULL, &p, NULL)))
throw std::runtime_error(std::string("loading texture failed (") + fname + ")");
return p;
}
Note: while we were at it we separated UI from business logic. You do not want to display messageboxes from inside constructors. Ever. You just want to notify the caller of the problem and the caller decides what to do (use another resource, try a different path, retry a download, write a warning message to the log, shut down etc.)
完整演示
#include <iostream>
#include <stdexcept>
///////////////////////////////////////////////////////
// mocking ID3D*
struct ID3D11ShaderResourceView;
enum ERROR_CODE { ERR_OK };
#define FAILED(e) (ERR_OK != (e))
static int gvDevice = 42;
ERROR_CODE D3DX11CreateShaderResourceViewFromFile(int, char const* fname, void*, void*, ID3D11ShaderResourceView**, void*) {
std::cout << "Loaded from " << fname << "\n";
return ERR_OK;
}
//
///////////////////////////////////////////////////////
struct frame{ virtual ~frame() = default; };
class button : public frame {
public:
button() {};
template <typename T1, typename T2>
button(T1 const& texture, T2 const& hover_texture)
: _texture(load(texture)),
_hover_texture(load(hover_texture))
{
};
private:
// TODO Rule-Of-Three constructor/destructorl
// SUGGEST: Rule-Of-Zero using shared pointers instead
ID3D11ShaderResourceView* _texture;
ID3D11ShaderResourceView* _hover_texture;
static ID3D11ShaderResourceView* load(ID3D11ShaderResourceView* v) { return v; }
static ID3D11ShaderResourceView* load(char const* fname) {
ID3D11ShaderResourceView* p = NULL;
if (FAILED(D3DX11CreateShaderResourceViewFromFile(gvDevice, fname, NULL, NULL, &p, NULL)))
throw std::runtime_error(std::string("loading texture failed (") + fname + ")");
return p;
}
};
#include <cassert>
int main() {
ID3D11ShaderResourceView* default_texture = NULL;
assert(!FAILED( D3DX11CreateShaderResourceViewFromFile(gvDevice, "default_texture.bin", NULL, NULL, &default_texture, NULL)));
try {
button button1("t1.bin", "hover1.bin");
button button2(default_texture, "hover2.bin");
button button3("t3.bin", default_texture);
button button4(default_texture, default_texture);
} catch(std::exception const& e) {
std::cout << "Oops: " << e.what() << "\n";
}
}
打印:
Loaded from default_texture.bin
Loaded from t1.bin
Loaded from hover1.bin
Loaded from hover2.bin
Loaded from t3.bin
还有很多需要改进的地方(例如,请参阅评论)但这是一个开始。