如何在类/函数模板中传递空参数

3

嘿,我正在尝试创建一个按钮模板类,它是基于按下时按钮将接收的(例如鼠标位置)和应该被调用的函数的指针构建的。

然而,按钮通常返回void且不带参数(当你按下按钮后会发生某些事情:它们不会带任何参数,只是被按下后执行某些操作)因此如何生成这些类的成员函数,因为显然不能将 void 作为参数类型?

如果需要,以下是源代码:

    template<typename Return = void, typename Arg1 = void, typename Arg2 = void> 
class Button 
{
private:
    boost::function<Return (Arg1, Arg2)> Function;
    //Return (*Function)(Arg1, Arg2);              // this didn't work so i tried boost::function

public:
    void Activate(Arg1, Arg2){ Function(Arg1, Arg2) ;};

    void SetFunction(Return (*Function)(Arg1, Arg2)){
        this->Function= Function;};

    //constructors
    Button(){ Function= 0;};

    Button( Return (*Function)(Arg1, Arg2)){  
        this->Function = &Function; };
};

你想如何使用你的模板?什么是指按钮通常返回void并且不带参数?你所指的按钮是哪些? - Jaime
@Jaime:按下按钮后会发生某些事情:它们不需要任何参数,只需按下即可执行某些操作。 - Griffin
2
按钮是生成事件(例如点击)的图形元素,您可以“挂钩”函数以响应这些事件,这就是按钮“执行”的方式。UI框架定义了您应该实现以响应这些事件的签名(参数类型和返回类型),因此您想如何使用您的模板?它的目的是什么,也许我们可以提出一些关于如何处理它的建议。 - Jaime
2个回答

5
您可以指定类型为void的模板规范,例如,您可以使用以下变化的类模板"button":
template <typename rtnVal, typename Val1, typename Val2>
class Button {
private:
    rtnVal(*Function)( Val1 val1, Val2 val2 );

public:
    Button() : Function( nullptr ) {}

    void SetFunction( rtnVal(*func)(Val1, Val2) ) {
        Function = func;
    }

    rtnVal RunFunction( Val1 val1, Val2 val2 ) { return Function( val1, val2 ); }
};

// Special void type, accepting arguments overload:
template < typename Val1, typename Val2 >
class Button< void, Val1, Val2 > {
private:
    void(*Function)(Val1 val1, Val2 val2);

public:
    Button() : Function( nullptr ) {}

    void SetFunction( void(*func)(Val1, Val2) ) {
        Function = func;
    }

    void RunFunction( Val1 val1, Val2 val2 ) { return Function( val1, val2 ); }

};

// Pure void type:
template<>
class Button<void, void, void> {
private:
    void(*Function)( void );

public:
    Button() : Function( nullptr ) {}

    void SetFunction( void(*func)() ) {
        Function = func;
    }

    void RunFunction() { 
        return Function();
    }
};

这将使您能够初始化并使用void作为参数。例如,给定一个void函数Print(),现在以下内容将是有效的:

void Print()
{
    std::cout << "Function has been called" << std::endl;
}

int main()
{
    Button< void, void, void > btn;

    btn.SetFunction( Print );

    btn.RunFunction();

    std::cout << "Finished";
}

我希望这能帮助澄清事情! :)

注意: nullptr 是C++0x关键字,如果你的编译器没有实现它,请使用 #define nullptr 0


是的。我不知道你可以用不同的模板覆盖一个类!但有一个问题:如果我在基类模板中放置其他成员数据/函数,其他重载是否也会自动包含它们?还是我必须将每个模板重载中的所有内容都复制一遍,而不仅仅是依赖于模板的函数? - Griffin
不幸的是,您需要重新声明成员函数/变量,尽管根据您的特化方式,这只是复制和粘贴并进行一些更改的问题。 - Thomas Russell

0

如果我理解正确,您希望用户可以在参数中使用0-2个参数?

如果您愿意使用c++0x,则可以使用可变模板。这将允许您使用所需的任意数量的参数。


许多编译器尚未实现可变参数模板,此外,模板特化提供了一种更简洁和直观的解决 OP 问题的方式。 - Thomas Russell
你会建议一个有约5个月编程经验的程序员现在学习Ox吗?最近有很多人建议这样做... - Griffin
你可以在任何时候开始学习C++0x标准。然而,C++0x标准的很多内容都是为了让高级编程概念更容易实现而设计的,因此你可能只有在拥有更多经验时才会发现它们的用处。 :) - Thomas Russell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接