C ++入門書の5番目の注意事項(第14章オーバーロード操作と型変換)呼び出し可能なオブジェクトと関数

1.5つのフォーム

呼び出し可能なオブジェクトには5つのタイプがあり、タイプは異なります。

説明
関数 戻り値の型と実際のパラメータの型
関数ポインタ 戻り値の型と実際のパラメータの型
ラムダ式 クラスタイプ
bindによって作成されたオブジェクト すべて
オーバーロードされた関数呼び出し演算子を持つクラス クラスタイプ

2.呼び出し可能なオブジェクトのタイプは異なりますが、呼び出しフォームは同じにすることができます

呼び出しフォームは、呼び出しの戻り値の型と、呼び出しに渡される実際のパラメーターの型を指定します。異なる呼び出し可能オブジェクトが同じ呼び出し形式を持つ場合があります。

例:タイプはすべてint(int、int)です

// ordinary function
int add(int i, int j) {
    
     return i + j; }

//lambda表达式,其产生一个未命名的函数对象类
auto mod = [](int i, int j) {
    
     return i % j; };

// function-object class
struct divide
{
    
    
    int operator()(int denominator, int divisor)
    {
    
    
        return denominator / divisor;
    }
};

//调用代码
//使用map映射
map<string,function<int(int,int)> > binops;
binops.insert({
    
    "+", add});
//error,不能将mode或divide insert到binope中,因为他们类型不是函数指针
binops.insert({
    
    "%", mod});

問題があります:それは均一に呼び出すことができません

3.均一に呼び出す方法は?

標準ライブラリ関数タイプ:標準ライブラリ関数タイプは、オブジェクトの呼び出し形式を表すために、ヘッダーファイル関数で定義されたテンプレートです。
を使用する場合は、特定の関数タイプを作成する必要があります。(それが表すオブジェクトの呼び出し形式を提供する必要があります)

オペレーティング 説明
関数f; fは、呼び出し可能オブジェクトを格納するために使用される空の関数です。これらの呼び出し可能オブジェクトの呼び出し形式は、タイプTと同じである必要があります。
関数f(nullptr); 空の関数を明示的に作成します
関数f(obj) 呼び出し可能なオブジェクトobjのコピーをfに格納します
f 条件としてfを使用します。fに呼び出し可能なオブジェクトが含まれている場合はtrue、それ以外の場合はfalse。
関数f(args)として定義されたメンバーのタイプ fでオブジェクトを呼び出します。パラメータはargsです。
result_type 関数型の呼び出し可能オブジェクトの戻り値の型
引数タイプ Tに1つまたは2つの実際のパラメーターがある場合に定義されるタイプ。
first_argument_type 最初の引数のタイプ
second_argument_type 2番目の引数のタイプ

例えば。function <int(int、int)>

function<int(int,int)> f1=add;  //函数指针
function<int(int,int)> f2=divide();  //函数对象类的指针
function<int(int,int)> f3=[](int i,int l){
    
    return i*j;};  //lambda
                                   
cout << f1(4,2) << endl;   // prints 6
cout << f2(4,2) << endl;   // prints 2
cout << f3(4,2) << endl;   // prints 8

例2。

//使用map映射
map<string,function<int(int,int)> > binops={
    
    
    {
    
    "+",add},  //函数指针
    {
    
    "-",std::minus<int>()},  //标准库函数对象
    {
    
    "/",divide()},  // 用户定义的函数对象
    {
    
    "*",[](int i,int j){
    
    return i*j;}},  //未命名的lambda
    {
    
    "%",mod} //已命名的lambda对象
};

//这个时候insert是可以的 
binops.insert( {
    
    "+", add} );	//函数指针
binops.insert( {
    
    "/",divide()} );	//函数对象
binops.insert( {
    
    "%", mod} );	//lambda表达式
binops.insert({
    
    "+"},[](int a,in b){
    
    return add(a,b);});//lambda表达式
binops.insert({
    
     "add" , [](int a, int b) {
    
    return add(a, b); } });//lambda表达式

cout << binops["+"](10, 5)<<endl;//调用add(10, 5)
cout << binops["-"](10, 5) << endl;
cout << binops["/"](10, 5) << endl;	//使用divide对象调用括号运算符
cout << binops["*"](10, 5) << endl;
cout << binops["%"](10, 5) << endl;//调用lambda函数对象
cout << binops["add"](10, 5) << endl;//调用lambda函数对象    

3.1オーバーロードされた関数の名前をfunction型のオブジェクトに直接格納することはできません。そうすると、あいまいさエラーが発生します。

int add(int i,int j){
    
    return i + j;}
Sales_data add(const Sales_data&,const Sales_data&);
map<string,funciton<int(int,int)>> binops;
binops.insert({
    
    "+",add});		//错误,不能区分是哪个add 

3.2解決策

関数名の代わりに関数ポインタを格納します。

int (*fp) (int,int) = add;
binops.insert("add",fp);	//正确,fp指向正确的add版本
  • C ++ 11の新しい標準ライブラリの関数クラスは、古いバージョンのunary_functionおよびbinary_functionとは関係ありません。後者の2つのクラスは、bind関数に置き換えられました。

[見積もり]

[1]コードfunctionObject.h

おすすめ

転載: blog.csdn.net/thefist11cc/article/details/114166651