深度探究C++中的函数重载的用法

C++ 允许同一范围内具有相同名称的多个函数的规范。这些函数称为重载函数,“重载”中对其进行了详细介绍。利用重载函数,程序员可以根据参数的类型和数量为函数提供不同的语义。
例如,采用字符串(或 char *)参数的 print 函数执行的任务与采用“双精度”类型的参数的函数执行的任务截然不同。重载允许通用命名并使程序员无需创建名称,例如 print_sz 或 print_d。下表显示了 C++ 使用函数声明的哪些部分来区分同一范围内具有相同名称的函数组。
重载注意事项

函数声明元素 是否用于重载?
函数返回类型 No
参数的数量
参数的类型
省略号存在或缺失
typedef 名称的使用
未指定的数组边界
const 或 volatile(见下文)

虽然可以根据返回类型区分函数,但是无法在此基础上对它们进行重载。仅当 Const 或 volatile 在类中用于应用于类的 this 指针(而不是函数的返回类型)时,它们才用作重载的基础。换言之,仅当 const 或 volatile 关键字遵循声明中函数的参数列表时,重载才适用。
以下示例阐述如何使用重载。

// function_overloading.cpp
// compile with: /EHsc
#include <iostream>
#include <math.h>

// Prototype three print functions.
int print( char *s );         // Print a string.
int print( double dvalue );      // Print a double.
int print( double dvalue, int prec ); // Print a double with a
// given precision.
using namespace std;
int main( int argc, char *argv[] )
{
const double d = 893094.2987;
if( argc < 2 )
  {
// These calls to print invoke print( char *s ).
print( "This program requires one argument." );
print( "The argument specifies the number of" );
print( "digits precision for the second number" );
print( "printed." );
exit(0);
  }

// Invoke print( double dvalue ).
print( d );

// Invoke print( double dvalue, int prec ).
print( d, atoi( argv[1] ) );
}

// Print a string.
int print( char *s )
{
cout << s << endl;
return cout.good();
}

// Print a double in default precision.
int print( double dvalue )
{
cout << dvalue << endl;
return cout.good();
}

// Print a double in specified precision.
// Positive numbers for precision indicate how many digits
// precision after the decimal point to show. Negative
// numbers for precision indicate where to round the number
// to the left of the decimal point.
int print( double dvalue, int prec )
{
// Use table-lookup for rounding/truncation.
static const double rgPow10[] = {
10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1, 10E0,
10E1, 10E2, 10E3, 10E4, 10E5, 10E6
  };
const int iPowZero = 6;
// If precision out of range, just print the number.
if( prec < -6 || prec > 7 )
return print( dvalue );
// Scale, truncate, then rescale.
dvalue = floor( dvalue / rgPow10[iPowZero - prec] ) *
rgPow10[iPowZero - prec];
cout << dvalue << endl;
return cout.good();
}

前面的代码演示了文件范围内的 print 函数重载。
默认参数不被视为函数类型的一部分。因此,它不用于选择重载函数。仅在默认参数上存在差异的两个函数被视为多个定义而不是重载函数。
不能为重载运算符提供默认参数。
参数匹配
选择重载函数以实现当前范围内的函数声明与函数调用中提供的参数的最佳匹配。如果找到合适的函数,则调用该函数。此上下文中的“Suitable”具有下列含义之一:

  • 找到完全匹配项。
  • 已执行不重要的转换。
  • 已执行整型提升。
  • 已存在到所需参数类型的标准转换。
  • 已存在到所需参数类型的用户定义的转换(转换运算符或构造函数)。
  • 已找到省略号所表示的参数。

编译器为每个参数创建一组候选函数。候选函数是这样一种函数,其中的实参可以转换为形参的类型。

为每个参数生成一组“最佳匹配函数”,并且所选函数是所有集的交集。如果交集包含多个函数,则重载是不明确的并会生成错误。对于至少一个参数而言,最终选择的函数始终是比组中的所有其他函数更好的匹配项。如果不是这样(如果没有清晰的胜者),则函数调用会生成错误。
考虑下面的声明(针对下面的讨论中的标识,将函数标记为 Variant 1、Variant 2 和 Variant 3):

Fraction &Add( Fraction &f, long l );    // Variant 1
Fraction &Add( long l, Fraction &f );    // Variant 2
Fraction &Add( Fraction &f, Fraction &f ); // Variant 3

Fraction F1, F2;

请考虑下列语句:

F1 = Add( F2, 23 );

前面的语句生成两个集:

集 1:其第一个参数的类型为 Fraction 的候选函数 集 2:其第二个参数可转换为类型 int 的候选函数
Variant 1 Variant 1(可使用标准转换将 int 转换为 long)
Variant 3

集 2 中的函数是具有从实参类型到形参类型的隐式转换的函数,在这些函数中,有一种函数的从实参类型到其形参类型的转换的“成本”是最低的。
这两个集的交集为 Variant 1。不明确的函数调用的示例为:

F1 = Add( 3, 6 );

前面的函数调用生成以下集:

集 1:其第一个参数的类型为 int 的候选函数 集 2:其第二个参数的类型为 int 的候选函数
Variant 2(可使用标准转换将 int 转换为 long) Variant 1(可使用标准转换将 int 转换为 long)

请注意,这两个集之间的交集为空。因此,编译器会生成错误消息。
对于参数匹配,具有 n 个默认参数的函数将视为 n+1 个单独函数,并且每个函数均具有不同数量的参数。
省略号 (...) 用作通配符;它与任何实参匹配。如果您未极其谨慎地设计重载函数集,这可能导致产生许多不明确的集。
注意
重载函数的多义性无法确定,直到遇到函数调用。此时,将为函数调用中的每个参数生成集,并且可以确定是否存在明确的重载。这意味着,多义性可保持在您的代码中,直到它们由特定函数调用引发。
参数类型差异
重载函数区分使用不同的初始值设定项的参数类型。因此,对于重载而言,给定类型的参数和对该类型的引用将视为相同。由于它们采用相同的初始值设定项,因此它们被视为是相同的。例如,max( double, double ) 被视为与 max( double &, double & ) 相同。声明两个此类函数会导致错误。
出于同一原因,对由 const 或 volatile 修改的类型的函数参数(出于重载的目的)的处理方式与基类没有什么不同。
但是,函数重载机制可以区分由 const 和 volatile 限定的引用和对基类型的引用。此方法可以编写诸如以下内容的代码:

// argument_type_differences.cpp
// compile with: /EHsc /W3
// C4521 expected
#include <iostream>

using namespace std;
class Over {
public:
  Over() { cout << "Over default constructor\n"; }
  Over( Over &o ) { cout << "Over&\n"; }
  Over( const Over &co ) { cout << "const Over&\n"; }
  Over( volatile Over &vo ) { cout << "volatile Over&\n"; }
};

int main() {
  Over o1;      // Calls default constructor.
  Over o2( o1 );   // Calls Over( Over& ).
  const Over o3;   // Calls default constructor.
  Over o4( o3 );   // Calls Over( const Over& ).
  volatile Over o5;  // Calls default constructor.
  Over o6( o5 );   // Calls Over( volatile Over& ).
}

输出

Over default constructor
Over&
Over default constructor
const Over&
Over default constructor
volatile Over&

指向 const 和 volatile 对象的指针也被认为和指向基类型的指针(以重载为目的)不同。
参数匹配和转换
当编译器尝试根据函数声明中的参数匹配实际参数时,如果未找到任何确切匹配项,它可以提供标准转换或用户定义的转换来获取正确类型。转换的应用程序受这些规则的限制:
不考虑包含多个用户定义的转换的转换序列。
不考虑可通过删除中间转换来缩短的转换序列。
最终的转换序列(如果有)称为最佳匹配序列。可通过多种方式使用标准转换将类型 int 的对象转换为类型unsigned long 的对象(如标准转换中所述):

  • 从 int 转换为 long,然后从 long 转换为 unsigned long。
  • 从 int 转换为 unsigned long。

第一个序列(尽管它实现了所需目标)不是最佳匹配序列 - 存在一个较短的序列。

下表显示了一组称为常用转换的转换,这些转换对确定哪个序列是最佳匹配项有一定的限制。该表后面的列表中讨论了常用转换影响序列选择的实例。
常用转换

从类型转换 转换为类型
type-name type-name &
type-name & type-name
type-name [ ] type-name*
type-name ( argument-list ) ( *type-name ) ( argument-list )
type-name const type-name
type-name volatile type-name
type-name* const type-name*
type-name* volatile type-name*

在其中尝试转换的序列如下:
完全匹配。用于调用函数的类型与函数原型中声明的类型之间的完全匹配始终是最佳匹配。常用转换的序列将归类为完全匹配。但是,不进行任何转换的序列被视为比进行转换的序列更佳:

  • 从指针,到指向 const(type* 指向 consttype*)的指针。
  • 从指针,到指向 volatile(type* 指向 volatiletype*)的指针。
  • 从引用,到对 const(type & 到 const type &)的引用。
  • 从引用,到对 volatile(type & 到 volatile type &)的引用。

使用提升的匹配。未归类为仅包含整型提升、从 float 到 double 的转换以及常用转换的完全匹配的任何序列将被归类为使用提升的匹配。尽管比不上完全匹配,但使用提升的匹配仍优于使用标准转换的匹配。

使用标准转换的匹配。未归类为完全匹配或仅包含标准转换和常用转换的使用提升的匹配的序列将归类为使用标准转换的匹配。在此类别中,以下规则将适用:
从指向派生类的指针到指向直接或间接基类的指针的转换优于到 void * 或 const void * 的转换。
从指向派生类的指针到指向基类的指针的转换会产生一个到直接基类的更好匹配。假定类层次结构如下图所示。

演示首选转换的关系图
从 D* 类型到 C* 类型的转换优于从 D* 类型到 B* 类型的转换。同样,从 D* 类型到 B* 类型的转换优于从 D* 类型到 A* 类型的转换。
此同一规则适用于引用转换。从 D& 类型到 C& 类型的转换优于从 D& 类型到 B& 类型的转换等。
此同一规则适用于指向成员的指针转换。从 T D::* 类型到 T C::* 类型的转换优于从 T D::* 类型到 T B::* 类型的转换等(其中,T 是该成员的类型)。
前面的规则仅沿派生的给定路径应用。考虑下图中显示的关系图。

演示首选转换的多继承关系图
从 C* 类型到 B* 类型的转换优于从 C* 类型到 A* 类型的转换。原因是它们位于同一个路径上,且 B* 更为接近。但是,从 C* 类型到 D* 类型的转换不优于到 A* 类型的转换;没有首选项,因为这些转换遵循不同的路径。
使用用户定义的转换的匹配。此序列不能归类为完全匹配、使用提升的匹配或使用标准转换的匹配。序列必须仅包含用户定义的转换、标准转换或要归类为使用用户定义的转换的匹配的常用转换。使用用户定义的转换的匹配被认为优于使用省略号的匹配,但比不上使用标准转换的匹配。
使用省略号的匹配。与声明中的省略号匹配的任何序列将归类为使用省略号的匹配。这被视为最弱匹配。
如果内置提升或转换不存在,则用户定义的转换将适用。基于将匹配的参数的类型选择这些转换。考虑下列代码:

// argument_matching1.cpp
class UDC
{
public:
  operator int()
  {
   return 0;
  }
  operator long();
};

void Print( int i )
{
};

UDC udc;

int main()
{
  Print( udc );
}

类 UDC 的可用的用户定义的转换来自 int 类型和 long 类型。因此,编译器会考虑针对将匹配的对象类型的转换:UDC。到 int 的转换已存在且已被选中。
在匹配参数的过程中,标准转换可应用于参数和用户定义的转换的结果。因此,下面的代码将适用:

void LogToFile( long l );
...
UDC udc;
LogToFile( udc );

在前面的示例中,将调用用户定义的转换 operator long 以将 udc 转换为类型 long。如果未定义到 long 类型的用户定义的转换,则按如下所示继续转换:使用用户定义的转换将 UDC 类型转换为 int 类型。将应用从 int 类型到 long 类型的标准转换以匹配声明中的参数。
如果需要任何用户定义的转换来匹配参数,则在计算最佳匹配时不会使用标准转换。即使多个候选函数需要用户定义的转换也是如此;在这种情况下,这些函数被认为是相等的。例如:

// argument_matching2.cpp
// C2668 expected
class UDC1
{
public:
  UDC1( int ); // User-defined conversion from int.
};

class UDC2
{
public:
  UDC2( long ); // User-defined conversion from long.
};

void Func( UDC1 );
void Func( UDC2 );

int main()
{
  Func( 1 );
}

Func 的两个版本都需要用户定义的转换以将类型 int 转换为类类型参数。可能的转换包括:

  • 从 int 类型转换到 UDC1 类型(用户定义的转换)。
  • 从 int 类型转换到 long 类型;然后转换为 UDC2 类型(一个两步转换)。

即使其中的第二个转换需要标准转换以及用户定义的转换,这两个转换仍被视为相等。

注意
用户定义的转换被认为是通过构造函数的转换或通过初始化的转换(转换函数)。在考虑最佳匹配时,两个方法被认为是相等的。
参数匹配和 this 指针
处理类成员函数的方式各不相同,具体取决于它们是否已被声明为 static。由于非静态函数具有提供 this 指针的隐式参数,因此将非静态函数视为比静态函数多一个参数;否则,将以相同的方式声明这些函数。
这些非静态成员函数要求隐含的 this 指针与通过其调用函数的对象类型匹配,或者对于重载运算符,它们要求第一个参数与该运算符应用于的对象匹配。

与重载函数中的其他参数不同,当尝试匹配 this 指针参数时,不会引入临时对象,且不会尝试转换。
当 – > 成员选择运算符用于访问成员函数时,this 指针参数具有 class-name* const 的类型。如果将成员声明为 const 或 volatile,则类型分别为 const class-name* const 和 volatile class-name * const。
. 成员选择运算符以相同的方式工作,只不过隐式 & (address-of) 运算符将成为对象名称的前缀。下面的示例演示了此工作原理:

// Expression encountered in code
obj.name

// How the compiler treats it
(&obj)->name

处理 –>* 和 .*(指向成员的指针)运算符的左操作数的方式与处理与参数匹配相关的 . 和 –>(成员选择)运算符的方式相同。
限制
多个限制管理可接受的重载函数集:

  • 重载函数集内的任意两个函数必须具有不同的参数列表。
  • 仅基于返回类型重载具有相同类型的参数列表的函数是错误的。

不能只根据一个静态类型和一个非静态类型来重载成员函数。
typedef 声明不定义新类型;它们引入现有类型的同义词。它们不影响重载机制。考虑下列代码:

typedef char * PSTR;

void Print( char *szToPrint );
void Print( PSTR szToPrint );

前面的两个函数具有相同的参数列表。 PSTR 是类型 char * 的同义词。在成员范围内,此代码生成错误。
枚举类型是不同的类型,并且可用于区分重载函数。
就区分重载函数而言,类型“array of”和“pointer to”是等效的。此情况仅适用于单维度数组。因此,以下重载函数会发生冲突并生成错误消息:

void Print( char *szToPrint );
void Print( char szToPrint[] );

对于多维数组,第二个和后续维度被视为类型的一部分。因此,它们可用来区分重载函数:

void Print( char szToPrint[] );
void Print( char szToPrint[][7] );
void Print( char szToPrint[][9][42] );

声明匹配
同一范围内具有同一名称的任何两个函数声明都可以引用同一函数或重载的两个不同的函数。如果声明的参数列表包含等效类型的参数(如上一节所述),函数声明将引用同一函数。否则,它们将引用使用重载选择的两个不同的函数。
需要严格遵守类范围;因此,在基类中声明的函数与在派生类中声明的函数不在同一范围内。如果使用与基类中的函数相同的名称声明派生类中的函数,则该派生类函数会隐藏基类函数,而不是导致重载。
需要严格遵守块范围;因此,在文件范围中声明的函数与在本地声明的函数不在同一范围内。如果在本地声明的函数与在文件范围中声明的函数具有相同名称,则在本地声明的函数将隐藏文件范围内的函数而不是导致重载。例如:

// declaration_matching1.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
void func( int i )
{
  cout << "Called file-scoped func : " << i << endl;
}

void func( char *sz )
{
  cout << "Called locally declared func : " << sz << endl;
}

int main()
{
  // Declare func local to main.
  extern void func( char *sz );

  func( 3 );  // C2664 Error. func( int ) is hidden.
  func( "s" );
}

前面的代码显示函数 func 中的两个定义。由于 char * 语句,采用 main 类型的参数的定义是 extern 的本地定义。因此,采用 int 类型的参数的定义被隐藏,而对 func 的第一次调用出错。
对于重载的成员函数,不同版本的函数可能获得不同的访问权限。它们仍被视为在封闭类的范围内,因此是重载函数。请考虑下面的代码,其中的成员函数 Deposit 将重载;一个版本是公共的,另一个版本是私有的。
此示例的目的是提供一个 Account 类,其中需要正确的密码来执行存款。使用重载可完成此操作。
请注意,对 Deposit 中的 Account::Deposit 的调用将调用私有成员函数。此调用是正确的,因为 Account::Deposit 是成员函数,因而可以访问类的私有成员。

// declaration_matching2.cpp
class Account
{
public:
  Account()
  {
  }
  double Deposit( double dAmount, char *szPassword );

private:
  double Deposit( double dAmount )
  {
   return 0.0;
  }
  int Validate( char *szPassword )
  {
   return 0;
  }

};

int main()
{
  // Allocate a new object of type Account.
  Account *pAcct = new Account;

  // Deposit $57.22. Error: calls a private function.
  // pAcct->Deposit( 57.22 );

  // Deposit $57.22 and supply a password. OK: calls a
  // public function.
  pAcct->Deposit( 52.77, "pswd" );
}

double Account::Deposit( double dAmount, char *szPassword )
{
  if ( Validate( szPassword ) )
   return Deposit( dAmount );
  else
   return 0.0;
}
(0)

相关推荐

  • C++函数重载详解及实例代码

    C++函数的重载 定义 在同一个作用域中,函数名相同,函数的参数列表不同的函数之间构成重载关系,在不同作用域中的同名函数遵循标识符隐藏的原则 ATTENTION:重载与函数的返回值类型无关,因为声明一个函数不需要返回类型,所以无法用来区分哪个函数 常函数和普通成员函数之间构成重载,重载时常对象调用常成员函数,一般对象调用一般成员函数 class A{ - public: void getVal()const{-} void getVal(){-} }; int main(){ const A a

  • 详解C++中的内联函数和函数重载

    内联函数(内嵌函数,内置函数) 调用函数时需要一定的时间和空间的开销.C++提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开.这种在函数调用处直接嵌入函数体的函数称为内联函数(inline function),又称内嵌函数或内嵌函数. 指定内联函数的方法很简单,只需要在定义函数时增加 inline 关键字. 注意:是在函数定义时增加 inline 关键字,而不是在函数声明时.在函数声明时增加 inline 关键虽然没有错误,但是也没有任何效果 inline 关键

  • C++中构造函数重载

    #include<stdio.h> class Test { private: int i; int j; int k; public: Test() { i=j=k=0; } Test(int v) { i=j=k=v; } void print() { printf("i= %d, j=%d, k=%d \n",i,j,k); } }; int main() { Test t1(1); Test t2=2; Test t3=Test(3); t1.print(); t2

  • C++中函数重载实例详解

    C++中函数重载实例详解 函数重载: 1.具有相同的名称,执行基本相同的操作,但是使用不同的参数列表. 2.函数具有多态性. 3.编译器通过调用时参数的个数和类型确定调用重载函数的哪个定义. 4.只有对不同的数据集完成基本相同任务的函数才应重载. 函数重载的优 点 1.不必使用不同的函数名 2.有助于理解和调试代码 3.易于维护代码 接下来直接上代码: #include <iostream> using namespace std ; void say_hello(void) { cout &

  • C++函数重载的深入解析

    我们在开瓶瓶罐罐的时候,经常会遭遇因各种瓶口规格不同而找不到合适的工具的尴尬.所以有时候就为了开个瓶,家里要备多种规格的开瓶器.同样是开个瓶子嘛,何必这么麻烦?于是有人发明了多功能开瓶器,不管啤酒瓶汽水瓶还是软木塞的红酒瓶都能轻松打开. 然而开瓶器的问题也会发生到程序设计中.比如我们要编写一个函数来求一个数的绝对值,然而整数.浮点型数.双精度型数都有绝对值,但为它们编写的函数返回值类型却是各不相同的.比如: 复制代码 代码如下: int iabs(int a);float fabs(float

  • 深度探究C++中的函数重载的用法

    C++ 允许同一范围内具有相同名称的多个函数的规范.这些函数称为重载函数,"重载"中对其进行了详细介绍.利用重载函数,程序员可以根据参数的类型和数量为函数提供不同的语义. 例如,采用字符串(或 char *)参数的 print 函数执行的任务与采用"双精度"类型的参数的函数执行的任务截然不同.重载允许通用命名并使程序员无需创建名称,例如 print_sz 或 print_d.下表显示了 C++ 使用函数声明的哪些部分来区分同一范围内具有相同名称的函数组. 重载注意事

  • 通过实例理解javascript中没有函数重载的概念

    将函数名想象为指针,也有助于理解为什么ECMAScript中没有函数重载的概念.如下例子: 复制代码 代码如下: function addSomeNum(num) {     return num+100; } function addSomeNum(num) {     return num+200; } var result=addSomeNum(100);//300 显然,这个例子中声明了两个同名函数,而结果则是后面的函数覆盖了前面的函数.以上代码实际上与下面的代码是一致的. 复制代码 代

  • JavaScript中的函数重载深入理解

    在JavaScript中有一种特殊的数据类型---Function类型,JavaScript的每个函数都是Function类型的实例.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定. <pre name="code" class="html">function sum(num1,num2) { return num1 +num2; } alert(sum(10,10)); //20 var other = sum; ale

  • C++语法中的函数重载和默认参数

    C语言中没有函数重载 C++语言中有函数重载 函数名相同,参数个数不同.参数类型不同.参数顺序不同 例如下面就是函数重载 void sum(int a, int b){ cout << a+b << endl; } void sum(int a, double b){ cout << a+b << endl; } 返回值类型与函数重载无关 返回值类型与函数重载无关,下面代码不构成重载,编译会报错 //返回值类型与函数重载无关 int func(){ retu

  • C++简明讲解缺省参数与函数重载的用法

    目录 一.缺省参数 1.1缺省参数概念 1.2缺省参数分类 二.函数重载 2.1函数重载概念 2.2名字修饰 一.缺省参数 缺省参数形象来说就是"备胎". 1.1缺省参数概念 缺省参数是声明或定义函数时为函数的参数指定一个默认值.在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参. #include<iostream> void P(int a = 3) { printf("%d", a); } int main() { P();//打印

  • php中substr()函数参数说明及用法实例

    本文实例讲述了php中substr()函数参数说明及用法.分享给大家供大家参考.具体如下: string substr(string $string ,int $start [, int $length ]),它可以用于在一个较长的字符串中查找匹配的字符串或字符,$string为所要处理的字符串,$start为开始选取的位置,$length为要选取的长度. $length 为正数据从左向右读取字符. $length 为负数时就右向左读取字符. string 必需,规定要返回其中一部分的字符串.

  • PHP中substr函数字符串截取用法分析

    本文实例讲述了PHP中substr函数字符串截取用法.分享给大家供大家参考,具体如下: PHP中substr函数定义如下: substr(string,start,length) 参数说明如下: string 必需.规定要返回其中一部分的字符串. start  必需.规定在字符串的何处开始. 正数 - 在字符串的指定位置开始 负数 - 在从字符串结尾开始的指定位置开始 0 - 在字符串中的第一个字符处开始 length 可选.规定被返回字符串的长度.默认是直到字符串的结尾. 正数 - 从 sta

  • python中enumerate函数遍历元素用法分析

    本文实例讲述了python中enumerate函数遍历元素用法.分享给大家供大家参考,具体如下: enumerate函数用于遍历序列中的元素以及它们的下标 示例代码如下: i = 0 seq = ['one', 'two', 'three'] for element in seq: print i, seq[i] i += 1 #0 one #1 two #2 three print '============' seq = ['one', 'two', 'three'] for i, elem

  • jquery中map函数遍历数组用法实例

    本文实例讲述了jquery中map函数遍历数组用法.分享给大家供大家参考.具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <

  • C++中回调函数(CallBack)的用法分析

    本文实例分析了C++中回调函数(CallBack)的用法.分享给大家供大家参考.具体分析如下: 如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过. 其错误是普通的C++成员函数都隐含了一个传递函数作为参数,亦即"this"指针,C++通过传递this指针给其成员函数从而实现程序函数可以访问C++的数据成员.这也可以理解为什么C++类的多个实例可以共享成员函数却-有不同的数据成员.由于this指针的作用,使得将一个CALL-BACK型的成员函数作为回调函数安装时

随机推荐