笔试面试那件小事(C++函数高级特征)

C++函数的高级特征

    重载(overloade)、内联(inline)、const和virtual是C++独有的而C不具备的四种机制。其中重载和内联机制既可以用于全局函数也可以用于类的成员函数,const与virtual机制仅用于类的成员函数。

 

1->函数重载:在C++程序中,可以将语义、功能相似的几个函数用同一个名字表示。

     重载的实现方法:函数重载只能靠参数而不能靠返回值类型不同来区分重载函数。编译器根据参数为每个重载函数产生不同的内部标识。例如:int Func(int x,int y)在C++中被编译成Func_int_int,而C语言不提供函数的重载,编译后的名称为Func。

经典面试题:如果C++程序要调用已经被编译后的C函数,该如何解决?

C++程序不能直接调用已经编译后的C函数,这是因为名称的问题。举个例子:一个函数叫做void foo(int x,int y),该函数被C编译器编译后再库中的名字为_foo,而C++则产生_foo_int_int之类的名字用来支持函数重载和类型安全连接,名称就不一样,因此不能直接调用。

C++提供了一个C连接交换指定符号extern "C"来解决这个问题

例如:

extern  “C”

{

    void  foo(int x,int y);

}

这就告诉C++编译器,函数foo是个C连接,应该到库中找名字_foo而不是找_foo_int _int.

另外还需要注意的是:并不是两个函数的名字相同就能够构成重载。全局函数和类的成员函数同名就不算重载,因为函数的作用域不同。

 

2->小心隐式转换导致重载函数产生二义性

例如:

#include <iostream.h>

void output(int x);       void output(float  x);

void output(int x){cout<<"output int"<<endl;}              void output(flaot x){cout<<"output float"<<endl;}

void main(){

    int x=1;  float y=1.0;   output(x); //output int 1

    output(y);  //output flaot 1               output(1); //output int 1

    output(0.5);  //error! ambiguous call 自动类型转换产生错误

    output(int(0.5));       output(float(0.5));

}

 

3->成员函数的重载覆盖和隐藏

成员函数被重载的特征:1,相同的范围(在同一类中) 2,函数名字相同  3,参数不同 4,virtual关键字可有可无

覆盖是指派生类函数覆盖基类函数,特征:1,不同的范围(分别位于派生类与基类)2,函数名字相同 3,参数相同 4,基类函数必须有virtual关键字

下面例子,函数Base::f(int) 和Base::f(float)相互重载,而Base::g(void)被Derived::g(void)覆盖

Class Base{

public:

void f(int x){cout<<"Base::f(int)"<<x<<endl;}

void f(float x){cout<<"Base::f(float)"<<x<<endl;}

virtual void g(void){cout<<"Base::g(void)"<<endl;}

};

class Derived:pubic Base{

public:

virtual void g(void){cout<<"Derived::g(void)"<<endl;}

};

 

4->隐藏规则

隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

a):如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无virtual关键字。基类的函数都将被隐藏

b):如果派生类的函数与基类的函数同名,并且参数也相同。但基类函数没有virtual关键字,此时基类的函数同样被隐藏

例如下面给出的例子:

1):函数Derived::f(float) 覆盖了Base::f(float)

2):函数Derived::g(int) 隐藏了Base::g(float),而不是重载

3):函数Derived::h(float)隐藏了Base::h(float),而不是覆盖

Class Base{

public:

virtual void f(float x){cout<<"Base::f(float)"<<x<<endl;}

void g(float x){cout<<"Base::g(float)"<<x<<endl;}

void h(flaot x){cout<<"Base::h(flaot)"<<x<<endl;}

};

class Derived:public Base{

public:

virtual void f(float x){cout<<"Derived::f(float)"<<endl;}

void g(int x){cout<<"Derived::g(int)"<<x<<endl;}

void h(float x){cout<<"Derived::h(float)"<<endl;}

};

void main(void){

Derived d;  Base *pb=&d;  Derived *pd=&d;

pb->f(3.14f); //Derived::f(flaot) 3.14

pd->f(3.14f);  //Derived::f(float) 3.14

pb->g(3.14f);  //Base::g(flaot) 3.14

pd->g(3.14f);  //Derived::g(int) 3

pb->h(3.14f);  //Base::h(float) 3.14

pd->h(3.14f);  //Derived::h(float) 3.14

}

 

摆脱隐藏:

Class Base{

public:

void f(int x);

};

class Derived:public Base{

public:

void f(char *str);

};

void Test(void){

Derived *pd=new Derived;    pd->f(10);  //ERROR

}

这个程序原本想调用Base::f(int x);但是被Derived中的f(char *)所隐藏。

所以将上述程序改为:

Class Derived:public Base{

public:

void f(char *str);  void f(int x){Base::f(x);}

}

 

4->函数的缺省值

a):参数缺省值只能出现在函数的声明中,而不能出现在定义体中

void Foo(int x=0,int y=0);   //正确

void Foo(int x=0,int y=0){} //错误

b):如果函数有多个参数,参数只能从后向前挨个缺省,否则将导致函数的调用出错

 

5->运算符的重载

在C++语言中,可以用operator加上运算符表示函数,就叫做运算符重载

如果运算符被重载为全局函数,那么只有一个参数的运算叫做一元运算符,有两个参数的运算符叫做二元运算符。如果运算符被重载为类的成员函数,那么一元运算符没有参数,二元运算符只有一个右侧参数,因为自己成了左侧参数。

运算符重载:

所有的一元运算符:建议重载为成员函数            =()[] ->  只能重载为成员函数   += -= /= *= &= |=等建议重载为成员函数  所有其他运算符  建议重载为全局函数

其中.  *   : ? 不能重载

 

6->内联函数

a):用内联取代宏代码(提高函数的执行效率)

b):inline必须与函数的定义体放在一块,如果与函数的声明放在一块将不能产生任何效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值