C++11中bind的使用错误


写了一个非常简单的应用,如下:

#include <functional>

typedef struct__Data

{

         intd;

}DataCB;

 

template <typenameT>

class ICallBack

{

public:

         ICallBack(){}

         ~ICallBack(){}

public:

        

          voidDoCallBack(T *data)

         {

                    printf("-------------------------------");

         }

public:

         /*boolisUse_ = true;*/

};

template <typenameTT>

class CallBackControl

{

public:

         usingDoControl = std::function<void(TT*)>;

public:

         CallBackControl(){}

         ~CallBackControl(){}

public:

         //实际使用给一个LAMBDA表达式就可以了。

         //voidControlBind(DoControl dc)

         //{

         //       this->doCallBack_ = dc;

         //}

         voidContorlBind(ICallBack<TT> *icb)

         {

                   this->doCallBack_= std::bind(&ICallBack<DataCB>::DoCallBack,icb,std::placeholders::_1);

         }

         voidoperator()(TT*t)

         {

                   if(nullptr!=this->doCallBack_)

                   {

                            this->doCallBack_(t);

                   }

 

         }

         intGetData(intd){

                   returnd;

         }

private:

         DoControl doCallBack_ =nullptr;

};

class StdThread 

{

public:

         StdThread(){}

         virtual~StdThread(){}

public:

         voidInitStdThread(ICallBack<DataCB>*icb){

                   this->cb_.ContorlBind(icb);

                   //this->cb_.GetData(10);

                   this->cb_(&db_);

         }

 

private:

         voidRun();

private:

                      //线程运行条件变量

         CallBackControl<DataCB>cb_;

         DataCB db_;

};

 

int _tmain(intargc,_TCHAR*argv[])

{

         ICallBack<DataCB> *icb =new ICallBack<DataCB>;

         StdThread std;

         std.InitStdThread(icb);

         system("pause");

         return0;

}

结果编译总是过不去,总是说参数不对"error C2064: 项不会计算为接受 1 个参数的函数",不能够使用一个参数。错误基本定位到fucntion的应用这里。也是无语了,把一些具体的模板都写成实例,还是报同样的错误。

1>          d:\vs2013_project\binduse\binduse\binduse.cpp(65): 参见对正在编译的函数 模板 实例化“std::function<void (TT *)>::function<ICallBack<DataCB>*&>(_Fx)”的引用
1>          with
1>          [
1>              TT=DataCB
1>  ,            _Fx=ICallBack<DataCB> *&
1>          ]
1>          d:\vs2013_project\binduse\binduse\binduse.cpp(65): 参见对正在编译的函数 模板 实例化“std::function<void (TT *)>::function<ICallBack<DataCB>*&>(_Fx)”的引用
1>          with
1>          [
1>              TT=DataCB
1>  ,            _Fx=ICallBack<DataCB> *&
1>          ]

实在没办法了,把ICallBack这个类改成了非模板类,将回调函数改成了模板函数,报模板函数不能是虚拟的,去除,结果还是报同样的错误。参数不对,参数不对,一点办法都没有了。

因为是模板类,所以报得错误稀里哗啦的也看不出到底什么原因,直到把第一个注释掉,才发现,程序报没有ControlBind这个函数,这才猛得明白,肯定犯了超低级的错误。重载函数的名字写错了,但是一直使用前面的那个函数名,所以才是模板不断的实例化,这才明白当初编译器报得那个错误里function调用了两次的原因,编译器不骗人啊。

看上面变红的两个函数,无语到底。自己挖坑自己添,怪不得别人啊。

<think>首先,用户的问题是:“我想了解C++bind函数的用法或解决相关问题请问C++bind函数使用方法示例”。这直接问bind函数的用法、方法和示例。系统级指令:我必须使用中文回答,确保行内数学表达式用$...$,独立公式用$$...$$并单独成段。LaTeX语法正确。生成相关问题。在引用段落末尾自然地添加引用标识,如[^1]。引用内容:用户提供了几个引用,但提到了“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。”不过,这是第一次交互,所以没有上一次的问题。引用是关于bind和lambda的,所以我会参考它们。引用[1]:boost::lambda的bind函数用法。引用[2]:std::bind使用,绑定成员函数。引用[3]:std::bind的基本用法。引用[4]:Lambda表达式的示例。由于用户问的是bind函数,我应该专注于C++标准库的std::bind,引用[2]和[3]直接相关。引用[1]是关于boost::lambda::bind的,但用户可能在问标准bind,所以我会以std::bind为主。回答结构:系统要求结构清晰,帮助用户逐步解决问题。真实可靠。大纲回答:1.**引入bind函数**:简要解释std::bind是什么、为什么使用它。2.**基本用法**:解释bind的工作原理。3.**示例代码**:提供几个示例,包括绑定自由函数、成员函数、改变参数顺序、绑定对象等。4.**与lambda的比较**:或许简要提到bind和lambda的区别,因为引用中有lambda。5.**常见问题**:解决可能的问题。6.**生成相关问题**:在最后添加相关问题。引用标识:在引用的段落末尾添加引用标识。例如,如果我从引用[2]或[3]获取信息,就在那里添加[^2]或[^3]。但由于用户说“上述引用仅供参考”,我应该尽量基于知识,确保真实,如果需要引用特定段落时再添加。确保中文回答。关键点:-std::bind用于将函数或成员函数绑定到参数,创建新的可调用对象。-用法示例:-绑定自由函数:类似引用[3]的示例。-绑定成员函数:类似引用[2],需要绑定对象。-使用占位符(placeholders)如_1,_2等来延迟提供参数。-改变参数顺序。完整示例代码:需要在回复中包含代码块。系统要求代码用代码块形式,如示例中的```python```,但这里是C++,所以用```c++```。生成相关问题:在回答结束前,类似示例中的“§§相关问题§§”部分。写回答:-开头:介绍bind函数。-主体:逐步解释用法和示例。-代码:放入代码块。-结尾:添加相关问题。</think> 以下是关于C++中`std::bind`函数(也称为`bind`函数)的详细解答。`std::bind`是C++标准库中的函数模板(定义在`<functional>`头文件中),用于将函数或成员函数绑定到参数上,创建一个新的可调用对象(例如函数对象)。它的主要作用是**部分应用**函数,即可以预先固定部分参数、改变参数顺序,或延迟调用。这在回调、事件处理和高阶函数编程中非常实用[^3]。我将逐步解释其使用方法、注意事项,并提供多个示例代码,确保内容真实可靠(基于C++11及以后标准)。 ### 1. `std::bind`的基本概念 `std::bind`的语法如下: ```cpp auto bound_function = std::bind(target_function, arguments...); ``` - **target_function**: 要绑定的目标函数(自由函数、成员函数、函数对象)。 - **arguments...**: 要绑定的参数。可以是具体值或占位符(placeholders,如`std::placeholders::_1`、`_2`),其中占位符表示该参数在调用时动态传入。 - **返回值**: 返回一个新的可调用对象(类型为`std::function`或类似),调用`bound_function(args...)`时等价于`target_function(bound_arguments...)`。 为什么使用`std::bind`? - **部分应用**: 固定部分参数,减少重复代码。 - **改变参数顺序**: 调整参数的接收顺序。 - **成员函数绑定**: 需要绑定到具体对象。 - **兼容旧代码**: 比Lambda表达式更通用在复杂场景(但新代码中Lambda更推荐)。 数学上,部分应用对应于高阶函数在函数式编程中的概念[^3]。 ### 2. 使用方法与示例 以下是`std::bind`的常见用法。所有代码示例都使用C++11及以上标准,编译时确保启用`-std=c++11`或更高版本。我在代码中加入了中文注释方便理解。 #### 示例1: 绑定自由函数(固定所有参数) 固定自由函数的所有参数,创建一个无参数的可调用对象。类似引用[3]的示例。 ```cpp #include <iostream> #include <functional> // 必须包含此头文件 // 定义自由函数 void free_function(int a, int b) { std::cout << "Sum: " << a + b << std::endl; } int main() { // 绑定free_function的前两个参数为10和20,创建新函数对象 auto bound_function = std::bind(free_function, 10, 20); // 调用时无需传参数(所有参数已固定) bound_function(); // 输出: Sum: 30 return 0; } ``` - **解释**: `std::bind(free_function, 10, 20)`绑定后,`bound_function()`等价于`free_function(10, 20)`。 - **应用场景**: 需要缓存或延迟计算。 #### 示例2: 使用占位符(动态绑定部分参数) 绑定部分参数,其余参数在调用时提供。占位符`_1`表示第一个动态参数、`_2`表示第二个,依此类推。 ```cpp #include <iostream> #include <functional> void free_function(int a, int b) { std::cout << "Sum: " << a + b << std::endl; } int main() { // 绑定free_function: 第一个参数固定为10,第二个参数动态传入(使用占位符_1) auto bound_function = std::bind(free_function, 10, std::placeholders::_1); // 调用时传入动态参数(20对应占位符_1) bound_function(20); // 输出: Sum: 30 // 也可以绑定为动态顺序 auto reverse_function = std::bind(free_function, std::placeholders::_2, std::placeholders::_1); reverse_function(30, 10); // 输出: Sum: 40 (参数顺序被改变) return 0; } ``` - **解释**: `std::bind(free_function, 10, _1)`绑定后,`bound_function(20)`等价于`free_function(10, 20)`。`reverse_function`改变参数顺序。 - **占位符用法**: `std::placeholders`命名空间中定义,常用`_1`到`_9`。 - **数学表示**: 占位符对应函数参数映射,例如`bind(f, a, _1)`等价于函数$$g(x) = f(a, x)$$[^3]。 #### 示例3: 绑定成员函数(对象绑定) 成员函数需要绑定到具体对象指针,因为成员函数有隐含的`this`指针。类似引用[2]的示例。 ```cpp #include <iostream> #include <functional> class MyClass { public: void print(int a, int b) { std::cout << "a: " << a << ", b: " << b << std::endl; } }; int main() { MyClass obj; // 绑定成员函数:指定对象指针(&obj)和参数 auto boundFunc = std::bind(&MyClass::print, &obj, 10, std::placeholders::_1); boundFunc(20); // 输出: a: 10, b: 20 // 绑定成员函数并固定所有参数 auto fixedFunc = std::bind(&MyClass::print, &obj, 30, 40); fixedFunc(); // 输出: a: 30, b: 40 return 0; } ``` - **解释**: `std::bind(&MyClass::print, &obj, ...)`中,`&MyClass::print`是成员函数指针,`&obj`是对象指针。占位符处理动态参数。 - **注意事项**: 对象必须有效(避免野指针)。成员函数必须通过对象调用。 #### 示例4: 绑定函数对象或Lambda `std::bind`也可以绑定到函数对象(Functor)或Lambda表达式,实现更复杂逻辑。 ```cpp #include <iostream> #include <functional> // 定义函数对象 struct Adder { int base; Adder(int b) : base(b) {} int operator()(int x) const { return base + x; } }; int main() { // 绑定函数对象 Adder add5(5); auto boundFunctor = std::bind(&Adder::operator(), &add5, std::placeholders::_1); std::cout << boundFunctor(10) << std::endl; // 输出: 15 // 绑定Lambda表达式 auto lambda = [](int x, int y) { return x * y; }; auto boundLambda = std::bind(lambda, std::placeholders::_1, 2); std::cout << boundLambda(5) << std::endl; // 输出: 10 (5*2) return 0; } ``` - **解释**: 函数对象需要指定操作符函数(如`operator()`)。Lambda表达式可直接绑定。 - **推荐**: 在新C++代码中(C++11+),Lambda通常更简洁(示例参考引用[4])。 ### 3. 注意事项与常见问题 - **性能**: `std::bind`创建的对象可能比Lambda稍慢,但优化后可忽略。占位符会增加编译开销。 - **占位符顺序**: 占位符按`_1, _2`等顺序索引调用时的参数,不强制连续。 - **参数传递**: 参数按值传递(除非使用`std::ref`包裹)。 - **与Lambda比较**: Lambda更灵活(可直接捕获变量),但`bind`在固定成员函数时更简单。 - **错误避免**: 确保对象生命周期有效;模板参数推导注意(使用`auto`简化)。 数学上,`std::bind`实现了函数组合和部分应用的范畴论概念[^3]。 ### 4. 相关问题 基于您的查询,我生成了以下相关问题供进一步学习:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值