标签:
主要内容:编译器编译的一般工作原理、对模版的分离式编译的特殊性(模版的特殊性)
链接: http://blog.csdn.net/pongba/article/details/19130
对程序进行编译时,对于函数调用,编译器只要求函数的原型在调用点是可见的,至于函数的定义是否存在不做检查(在对程序进行链接时才检查函数的定义)。类似的,对于对象声明,编译器只要求所属的类定义在声明点是可见的,至于各成员函数的定义是否存在则不进行检查。因此,为了提高程序的可读性和可维护性,我们通常将函数原型和类定义放在头文件(.h文件)中,而函数定义(包括类成员函数的定义)则放在源文件(.cpp文件,又称实现文件)中。
但是,模版编译则有所不同。从本质上说,模版并不是代码,而是指导编译器生成代码的指令,模版实例才是真正的程序代码。编译器看到模版定义的时候,不会立刻产生代码,只有在看到模版的使用(如调用函数模版、使用类模版定义对象或通过对象调用类模板的成员函数)时,才会进行实例化,使用特定的模版实例代码。而为了成功地进行实例化,编译器必须能够使用相应的函数定义,因此,模版编译要求模版的定义和实现采用特别的文件组织方式。
C++语言中定义了两种编译模式:包含编译模式(inclusion compilation model)和 分离编译模式(separate compilation model)。
......
——摘自《C++语言程序设计》(蒋爱军、刘红梅、王勇、梁小萍编著)P349 13.3.3 模版编译与类模板的实现
......
提示:分离编译模式实现起来比较困难,因此,所有的C++编译器都支持包含编译模式,而只有某些C++编译器支持分离编模式。程序员在编译使用自定义的模版的程序时,需要查阅编译器的用户指南,以确定自己所用的编译器支持那种编译模式。
——摘自《C++语言程序设计》(蒋爱军、刘红梅、王勇、梁小萍编著)P352 13.3.3 分离编译模式
在此演示一般的编译实例,和对于 函数或类模版的编译实例。
(1)一般的编译:
以自定义类date为例,首先创建一个Console Application project工程文件(选用C++实现),向其中添加 date.h 和 date.cpp 两个文件,其中,date.h 存放 类的声明,而 date.cpp 对 date.h 中声明的类中的函数做具体的函数定义(函数实现)。
①date.h仅需要存放对类的声明就好。
//**********************************************************************************
//Date.h
//对类Date及其派生类Ndate 进行声明
//**********************************************************************************
class Date
{
public:
Date(int initYear=2014, int initMonth=1, int initDay=1);
void set(int nYear,int nMonth, int nDay);
int getYear()const;
int getMonth()const;
int getDay()const;
void print()const;
void increment();
void decrement();
private:
int month;
int year;
int day;
};
class Ndate: public Date
{
public:
Ndate(int initYear=2014, int initMonth=10, int initDay=16);
void n_increment(int n);
void n_decrement(int n);
};
②date.cpp 需要 include"date.h" 然后再对 date.h 中声明的类中的函数做具体的函数定义。(注意:实现文件包含头文件)
//**********************************************************************************
//Date.cpp
//对Date.h 中声明的函数进行定义
//**********************************************************************************
#include "date.h"
#include <iostream>
#include <iomanip>
using namespace std;
int daysInMonth(int mo,int yr);
Date::Date(int initYear, int initMonth, int initDay)
{
year=initYear;
month=initMonth;
day=initDay;
}
void Date::set( int nYear,int nMonth, int nDay)
{
year=nYear;
month=nMonth;
day=nDay;
}
int Date::getYear()const
{
return year;
}
int Date::getMonth()const
{
return month;
}
int Date::getDay()const
{
return day;
}
void Date::print()const
{
switch(month)
{
case 1:
cout<<setw(9)<< "January"<<setw(3);
break;
case 2:
cout<<setw(9)<< "Fabruary"<<setw(3);
break;
case 3:
cout<<setw(9)<< "March"<<setw(3);
break;
case 4:
cout<<setw(9)<< "April"<<setw(3);
break;
case 5:
cout<<setw(9)<< "May"<<setw(3);
break;
case 6:
cout<<setw(9)<< "June"<<setw(3);
break;
case 7:
cout<<setw(9)<< "July"<<setw(3);
break;
case 8:
cout<<setw(9)<< "August"<<setw(3);
break;
case 9:
cout<<setw(9)<< "September"<<setw(3);
break;
case 10:
cout<<setw(9)<< "October"<<setw(3);
break;
case 11:
cout<<setw(9)<< "November"<<setw(3);
break;
case 12:
cout<<setw(9)<< "December"<<setw(3);
break;
}
cout<< day << setw(5)<<year<< endl;
}
void Date::increment()
{
day++;
if(day > daysInMonth(month,year))
{
day=1;
month++;
if( month>12)
{
month=1;
year++;
}
}
}
void Date::decrement()
{
day--;
if(day==0)
{
if(month==1)
{
day=31;
month=12;
year--;
}
else
{
month--;
day= daysInMonth(month, year);
}
}
}
int daysInMonth(int mo,int yr)
{
switch (mo)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case