函数指针
函数指针实际上代表一个函数在内存中的入口地址,要正确地定义一个函数指针,必须同时指明函数的返回值类型和函数的参数列表
定义函数指针的形式: ReturnType (* pfunc) (var - list);ReturnType是指函数的返回值类型,pfunc则是函数指针,var-list是函数的参数列表。
一个使用函数指针的例子:
#include <iostream>
using namespace std;
class DoubleValue
{
public:
double GetValue()
{
return 6.7;
}
static int ReInt() //ReInt 理解为作用域受限的外部函数
{
return 3.3;
}
};
//定义一个函数指针
typedef int (*p)();
//重载操作符
double operator+(DoubleValue &d, p func)
{
return d.GetValue() + func();
}
int main()
{
DoubleValue obj;
p p1 = obj.ReInt;
cout<<obj+p1;
return 0;
}
函数指针作为另一个函数的参数传递时,对函数指针的声明可以采用显式的方式,也可以采用“隐式”的方式进行。
一个显式和隐式调用函数指针的例子:
#include <iostream>
using namespace std;
int fun()
{
cout<<"my fun()\n";
return 1;
}
void invoke1(int (*ptrfun)()) //显式声明函数指针
{
cout<<(*ptrfun)()<<endl;
}
void invoke2(int fun()) //隐式声明函数指针,,出现参数列表中的函数原型只可能用于描述某个参数
//所以它描述的是一个函数指针
{
cout<<fun()<<endl;
}
int main()
{
invoke1(fun);
invoke2(fun);
return 0;
}
函数重载和函数覆盖的比较:
1.函数重载发生在同一作用域的两个函数之间,二函数覆盖则发生在基类的成员函数和派生类的成员函数之间;
2.形成重载的两个函数,要求其函数名必须相同,而参数列表一定不同,对返回值类型不做要求;而形成覆盖的两个函数,则要求函数名、参数列表和返回值类型都相同;
3.类的静态成员函数可与非静态成员函数发生重载,而函数覆盖只可能发生在基类的非静态成员函数和派生类的非静态成员函数之间;
4.发生函数调用时,重载函数的入口时在编译时确定的(静态联编),而发生虚调用(使用函数覆盖)时,函数的入口地址是在运行时决定的(动态联编)。
函数覆盖的例子:
#include <iostream> using namespace std; class A { public: void useFunc() { cout<<"A\n"; } }; class B:public A { public: void useFunc() //函数覆盖 { cout<<"B\n"; } }; int main() { B b; b.useFunc(); b.A::useFunc(); //调用A中的成员函数useFunc(),必须指明其作用域 return 0; }
操作符重载1.只有C++预定义的操作符集中的操作才可以被重载,程序员不可以自己定义新的操作符;
2.操作符本质上等同于一个函数,所以C++操作符理解成“操作符函数”。操作符函数名是由operator关键字后跟操作符构成的;
3.操作符所带操作数的个数不允许改变,操作符之间的优先级不允许改变;
4.可以有两种形式进行操作符重载:
第一种:把操作符函数视为一个外部函数,所有的操作数作为这个函数的参数。由于操作符函数往往需要访问类对象的私有成员,所以一般将这个外部函数声明为参数类型的友元函数。第二种:将操作符函数作为类的成员函数看待,这是操作符的第一个操作数一定是该类的对象。
5.不允许为基本数据类型定义其他操作,换句话说,就是操作数中至少要有一个用户自定义的类类型或枚举类型。
6.有些操作符不允许重载,例如 .、.*、::、?:
7.操作符函数有两种调用方式:隐式调用和显式调用,一般情况下采用隐式调用操作符函数;
8.可以将类型(包括基本数据类型和用户自定义的类型)作为特殊的操作符,即类型转换操作符;在某个类中对这个类型操作符进行重载,就可以达到类型转换的目的;
9除了对 ( )操作符外,对其他重载操作符提供参数的默认值都是非法的。
操作符函数 隐式调用和显式调用的例子:
#include <iostream>
using namespace std;
class Complex
{
double real;
double image;
public:
Complex(double r = 0.0, double i = 0.0)
{
real = r;
image = i;
}
void Show()
{
cout<<real<<"+"<<image<<"i"<<endl;
}
Complex operator+(const Complex&);
};
Complex Complex::operator+(const Complex&c)
{
return Complex(real+c.real, image + c.image);
}
int main()
{
Complex c1(1.1, 2.1);
Complex c2(2.3, 4.4);
Complex c3 = c1 + c2; //隐式调用
c3.Show();
Complex c4 = c1.operator+(c2); //显式调用, 可以看出两个的效果是一样的
c4.Show();
return 0;
}
类型操作符的使用:
#include <iostream>
using namespace std;
class A
{
int m;
public:
A(int i)
{
m = i;
}
void Show()
{
cout<<m<<endl;
}
};
class B
{
int n;
public:
operator A() //定义一个类型操作符
{
return A(n);
}
B(int i)
{
n = i;
}
};
int main()
{
B b(5);
//A a = b; //等价于 A a = A(b); 或者 A a = (A)b;
//A a = A(b);
A a = (A)b;
a.Show();
return 0;
}