关闭

王老师 C++ 函数重载和模板 第一讲

1806人阅读 评论(0) 收藏 举报

1.const 

示例代码:

#include <iostream>
int main(void)
{
 int x = 3;
 const int y = x;
 const int *p = &y;
 const int *c = &x;

 //error: l-value specifies const object
 //*p = 5;

 //error: cannot convert from 'const int *' to 'int *'
 //int *t = &y;

 //---------------------------------------------------
 int * const px = &x;

 //error: cannot convert from 'const int *' to 'int *const '
 //px = p;

 return 0;
}

const变量主要用于函数参数,使调用者不可改变传入的指针指向的内容。

2. volatile

下面的说明来自msdn,告诉编译器,这个变量可被其他进程修改,不要对其进行优化。

Objects declared as volatile are not used in optimizations because their value can change at any time. The system always reads the current value of a volatile object at the point it is requested, even if the previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment.

One use of the volatile qualifier is to provide access to memory locations used by asynchronous processes such as interrupt handlers.

3.引用

变量的别名,对一个变量的引用的任何操作都是对本变量操作,必须初始化。

定义语法: 类型名 &引用名 = 被引用的变量;

引用是一个指针,但不用指针的语法。

引用必须指向一个变量;引用一旦指向一个变量,即不能指向其他的变量。

4.inline将把函数代码展开,同时作类型检查,而宏则不作类型检查。

5.namespace

命名空间是累计的,可跨越文件。

给命名空间起简名: namespace 别名  = 命名空间名;

using指示符: using namespace 命名空间名;

示例代码:

#include <iostream>
using namespace std;

namespace n1
{
 int x = 1;
 int fun(int x)
 {
  cout << "in namespace 1" << endl;
  return x + 1;
 }
 namespace n2
 {
  int x = 2;
  int fun(int x)
  {
   cout << "in namespace 2" << endl;
   return x + 2;
  }
 }
}

int x = 3;
int fun(int x)
{  
 cout << "in namespace std";
 return x + 3; 
}

int g(int x)
{
 {
  using namespace n1::n2;
  int x = 4;
  return n1::n2::fun(x);
 }
}

int main(void)
{
 cout << fun(x) << endl;
 cout << n1::fun(n1::x) << endl;
 cout << n1::n2::fun(n1::x) << endl;
 cout << n1::n2::fun(n1::n2::x) << endl;
 cout << g(3);
 return 0;
}
6.函数的重载

用一个名字定义多个参数,各个参数用形参个数和类型区分。

必须在同一个命名空间中,不能用返回值区分。

示例程序:

#include <iostream>
using namespace std;

int abs(int x)
{
 return x > 0 ? x : -x;
}

double abs(double x)
{
 return x > 0 ? x : -x;
}

char abs(char x)
{
 return x > 0 ? x : -x;
}

float abs(float x)
{
 return x > 0 ? x : -x;
}

short abs(short x)
{
 return x > 0 ? x : -x;
}

long abs(long x)
{
 return x > 0 ? x : -x;
}

int main(void)
{
 double a = 3.4;

 //注释掉double类型的abs函数后
 //error: ambiguous call to overloaded function
 cout << abs(a);

 return 0;
}

<补充>
1.名字空间 完全限定名(Fully Qualified Names),两种解决方法:
(1)使用typedef 把引用序列映射为一个较短的类型名以简化书写;
(2)使用using声明和using指令
using声明语法:
using namespace::member;
or
using class::member;
using指令语法:
using namespace 名字空间名;
名字空间一般用来分隔逻辑或业务上相互独立的模块。
2.实现范型编程的方法
(1)使用带参数的宏;
(2)使用void*,例如qsort();
(3)使用通用的根类和虚函数,比如java中的Object;
(4)使用模板技术。
模板最适合实现范型编程,它不仅直观,而且是类型安全的,不会带来任何额外的运行时开销。
template-->(实例化)Classes-->(实例化)Objects
template-->(实例化)Functions
如果设计的类的行为(接口)依赖于其所操作的数据类型,那么选用模板,否则选用继承和虚函数。
3.模板实例化
两个模板类或两个模板函数是类型等价的,当且仅当下列条件同时成立:
(1)模板的名字相同;
(2)类型实参完全相同(兼容的类型为不同类型);
(3)非类型实参的值完全相等;
(4)当类型实参为另一种模板时,它们也必须相同。
模板的实例化发生在第一次使用该模板时,而不是在其定义或编译时。显式实例化由关键字template或typename后跟带模板实参的模板声明(不是定义)或类型映射组成。
4.模板的特化(specialization)
就是针对某种特别的类型参数重新实现基本的模板,一般是出于对时空效率的优化或者满足特殊的需要。例如:STL的vector<bool>。
模板特化分为显式特化(Explict Specialization)和部分特化(Particial Specialization)(vc不支持),在范型编程的traints技术中使用比较多。 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1041926次
    • 积分:15000
    • 等级:
    • 排名:第784名
    • 原创:419篇
    • 转载:222篇
    • 译文:0篇
    • 评论:78条
    最新评论
    Learning