`
lingyibin
  • 浏览: 190675 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

高质量C++/C编程学习笔记(五)----- 基础函数的高级特性

阅读更多

1、重载:

只能靠参数而不能靠返回值类型的不同来区分重载函数。编译器根据参数为每个重载函数产生不同的内部标识符。

如void Test(int …);void Test(char…);void Test(float…); 编译器有可能会为这三个函数产生三个像_test_int、_test_char、_test_float 之类的内部标识符,当做不同的编译器可能产生不同风格的内部标识符,上面这种风格是我自己推测的。这也许就是重载的原理吧。

有一点需要注意的是,并不是函数名相同参数不同就能构成重载,如全局函数和类的成员函数同名就不算:

 

void Print(…);  //  全局函数 
 class A 
 {… 
  void Print(…); //  成员函数 
  }

这时可以用::print(……) 来标识全局变量 

还有,写重载时,不要写成如下形式:

 

void output( int x); 
void output( int x, float y=0.0); 

 这样的话,调用ouput(1); 就会报错。

 

2、extern “C” 

举例:void foo(int x, int y); 

该函数被 C 编译器编译后在库中的名字为_foo,而 C++编译器则会产生像_foo_int_int之类的名字用来支持函数重载和类型安全连接。由于编译后的名字不同,C++程序不能直接调用 C 函数。C++提供了一个 C 连接交换指定符号 extern“C”来解决这个问题。

例如: 

extern “C” 

   void foo(int x, int y); 

   … //  其它函数 

或者写成 

extern “C” 

   #include “myheader.h” 

   … //  其它 C 头文件 

 

这就告诉 C++编译译器,函数 foo 是个 C 连接,应该到库中找名字_foo 而不是找_foo_int_int。C++编译器开发商已经对 C 标准库的头文件作了 extern“C”处理,所以我们可以用#include  直接引用这些头文件。

 

3、重写与覆盖中的与“隐藏”相关的规则

 

  3.1 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无 virtual 关键字,基类的函数将被隐藏(注意别与重载混淆)

 

  3.2 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有 virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

给个网上的例子

 

#include <iostream.h> 
 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(float x){ cout << "Base::h(float) " << x << endl; } 
}; 
 class Derived : public Base 
{ 
public: 
  virtual void f(float x){ cout << "Derived::f(float) " << x << endl; } 
  void g(int x){ cout << "Derived::g(int) " << x << endl; } 
  void h(float x){ cout << "Derived::h(float) " << x << endl; } 
}; 
void main(void) 
{ 
Derived  d; 
Base *pb = &d; 
Derived *pd = &d; 
// Good : behavior depends solely on type of the object 
pb->f(3.14f); // Derived::f(float) 3.14  
pd->f(3.14f); // Derived::f(float) 3.14 
 
// Bad : behavior depends on type of the pointer 
pb->g(3.14f); // Base::g(float) 3.14  
pd->g(3.14f); // Derived::g(int) 3        (surprise!) 
 
// Bad : behavior depends on type of the pointer 
pb->h(3.14f); // Base::h(float) 3.14      (surprise!) 
pd->h(3.14f); // Derived::h(float) 3.14  
} 

 

 如果语句 pd->f(10)一定要调用函数 Base::f(int),那么将类 Derived 修改为如下即可。

 

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

 

4、用内联取代宏代码

 

预处理器用复制宏代码的方式代替函数调用,省去了参数压栈、生成汇编语言的CALL 调用、返回参数、执行 return 等过程,从而提高了速度。使用宏代码最大的缺点是容易出错,如:

 

 #define MAX(a, b)       (a) > (b) ? (a) : (b) 
//下面的语句  就会得不到自己想要的结果
result = MAX(i, j) + 2 ; //相当于 result = (i) > (j) ? (i) : (j) + 2 ; 

 宏还有一个缺点,就是无法操作类的私有数据成员。

这时可以考虑用内联函数 

使用如下: 

 void Foo(int x, int y);   // 先声明

 inline void Foo(int x, int y) // inline 与函数定义体放在一起 , 不用放在声明上,这样比较规范一点

 { 

  … 

 }

其实 内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。以下情况不宜使用内联: 

(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。 

(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。

 

5、将成员函数的定义体放在类声明之外

放在类声明之中虽然能带来书写上的方便,但不是一种良好的编程风格,应该改成如下形式: 

 

 //  头文件 
class A 
 { 
public: 
  void Foo(int x, int y);  
 } 
 //  定义文件 
 inline void A::Foo(int x, int y) 
{ 
… 
}
 

 

 

0
0
分享到:
评论

相关推荐

    高级C语言 C 语言编程要点

    59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 ...

    高级C语言详解

    59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 ...

    高级进阶c语言教程..doc

    59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 ...

    史上最强的C语言资料

    59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 ...

    c语言难点分析整理,C语言

    59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 ...

    免费下载:C语言难点分析整理.doc

    59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 ...

    C语言难点分析整理

    59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 ...

    C语言难点分析整理.doc

    59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全...

    高级C语言.PDF

    PC-Lint与C\C++代码质量 ........................................................................................................ 132 32. spirntf函数使用大全...............................................

    asp.net知识库

    VS2005 ASP.NET本地化学习笔记&感受 在自定义Server Control中捆绑JS文件 Step by Step 深度解析Asp.Net2.0中的Callback机制 使用 Web 标准生成 ASP.NET 2.0 Web 站点 ASP.NET 2.0基于SQLSERVER 2005的aspnetdb.mdf...

Global site tag (gtag.js) - Google Analytics