转载自:http://www.cnblogs.com/staring-hxs/p/3701742.html

声明( declaration )是告诉编译器某个东西的名称和类型( type ),但略去细节。

下面是声明的例子:

 1 extern int x;     //对象(object )声明
 2 
 3 size_t numDigits( int number );   //函数声明( function ) 声明
 4 
 5 class Widget;    //类( class )声明 
 6 
 7 template<typename T>
 8 
 9 class  GraphNode;         //类模版( template )声明
10 
11  
12 template<typename T>
13 
14 T function( T number1, T number 2);   //函数模版声明

定义( definition )是提供编译器一些声明所遗留的细节。

对对象( object )而言,定义是编译器为此对象分配内存。

对函数( function ) 或 函数模版( function template ) 而言,定义是提供代码本体。

对类( class ) 或 类模版( class template )而言,定义列出他们的成员。

下面是定义的例子:

 1 int  x;                                         //对象的定义
 2 
 3 size_t numDigits( int number )     //函数的定义
 4 {
 5   //do something
 6   return 1;
 7 }
 8  
 9 class Widget    //类的定义
10 {
11   public:
12     Widget();
13     ~Widget();
14 15 }
16 
17 template< typename T >    //类模版的定义
18 class  GraphNode
19 {
20  public:
21     GraphNode();
22    ~GraphNode();
23   ….
24 }
25  
26 template<typename T>
27 T function( T number1, T number 2)  //函数模版的定义
28 {
29   return number1 + number2;
30 }

初始化( Initialization )是”给予对象初值”的过程。

对用户自定义类型的对象而言,初始化由构造函数执行。默认( default )构造函数是一个可被调用而不带任何参数,这样的默认构造函数要么没有参数,要么就是每个参数都有缺省值。

 1 class  A 
 2 { 
 3 public: 
 4     A();                 //默认构造函数 
 5 };
 6 
 7 class B 
 8 { 
 9 public: 
10     explicit B( int x=0, bool b=true );     //默认构造函数
11 
12 };
13 
14 class C 
15 { 
16 public: 
17     explicit C( int x );    //不是默认构造函数,是带参数的构造函数 
18 };

上述的 class B 和 class C的构造函数都被声明为 explicit, 关于 explicit,请参考explicit浅谈。它可用来阻止隐式转换( implicit type conversions )为了防止隐式使用拷贝构造函数,但仍可以进行显示类型转换( explicit type conversions );

explicit浅谈

在C++中,explicit关键字主要用于防止隐式转换,用于修饰构造函数、复制构造函数。

例如有一个类:

 1 class A 
 2 { 
 3 public: 
 4     A( int count ) : m_data( count ){} 
 5 private: 
 6     int m_data; 
 7 };
 8 
 9 int main() 
10 { 
11     A a = 0;  //ok , conver int to A 
12 
13     a = 10; // 这里是什么操作?  等价与 a.operator=( 10 );
14 }

1、 A a = 0;

首先编译器( compiler )认为这样写是不符合规矩的,因为 A = A才是正常行为但是它不放弃,通过搜索发现A可以根据一个int构造,同时这个A( int count)没有用explicit修饰过。那么A a=0编译器将自动将整形转为A类对象,实际上等同下面操作

A temp( 0);

A a = temp;

这里需要说明的是 A a = tmp 调用的是拷贝构造函数( copy constructor),虽然clas A中没有,但是通常不写的话,编译器会生成一个成员逐一赋值( memberwise assignment )的拷贝构造函数,底层实现通常会以memcpy进行

 

2、a = 10;

首先这里同构造函数一样,编译器( compiler ) 无法进行直接操作,等同于代码

a.operator=( 10 );

需要注意的是, a = tmp是调用的赋值运算符( assignment操作 ), 同构造函数一样,我们自己不写, 编译器会生成一个成员逐一赋值(memberwise assignment)操作。

 

3、fun( A a )

同样, fn(10)也是不对的, 但是"按照惯例", 会有: 
A tmp(10); 
fn( tmp ) ;

 

注意:拷贝构造函数的写法只能是 T::T(const T &);

而赋值运算符的写法可以多变,即以任意T为例:

可以有

T &operator = (int n); 
也可有 
T &operator = (const char *);

当然, 你要确认如此的定义是对T而言有意义.

posted on 2014-11-02 23:36  归海一刀  阅读(172)  评论(0)    收藏  举报