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

所以我尝试了:

我不想重载构造函数,因为这将创建 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.)

完整演示

Live On Coliru

#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

还有很多需要改进的地方(例如,请参阅评论)但这是一个开始。