大胖的部落格

Just a note

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  112 随笔 :: 0 文章 :: 3 评论 :: 0 Trackbacks
mutable
当类的数据成员声明为mutable时,该数据成员的值在const成员函数中也可以被改变。
不可与const和static一起用。
class Base
{
public:
    Base():i(
0){}

    
void ChangeValue() const
    
{
        
//assign value to the mutable data member
        i=1;
    }


    mutable 
int i;
}
;




extern
1.extern用在变量声明中常常有这样一个作用,你在*.c文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放在*.h中并用extern来声明。

2.如果函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其它作用。即下述两个函数声明没有区别:
  extern int f(); 和int f();

如果不想包含头文件,那么在c/cpp中声明该函数。一般来说,声明定义在本文件的函数不用“extern”,声明定义在其他文件中的函数用“extern”,
这样在本文件中调用别的文件定义的函数就不用包含头文件include “*.h”来声明函数,声明后直接使用即可。



extern "C"
c++编译器会将函数改名后保存到obj文件中,c编译器不会。
所以在c++代码中include一个声明c函数的头文件,link该c函数库时,会找不到函数定义。
这时在该函数声明前加上关键字extern "C", 可以保证编译器link时按照c函数的规则去库中寻找该函数定义。

//extern "C"的惯用法

//1.在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:
extern "C"
{
    #include
"cExample.h"
}

//而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。

//C++引用C函数例子工程中包含的三个文件的源代码如下:
/* c语言头文件:cExample.h */
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x,int y);
#endif

/* c语言实现文件:cExample.c */
#include
"cExample.h"
int add( int x, int y )
{
    
return x + y;
}


// c++实现文件,调用add:cppFile.cpp
extern "C" 
{
    #include
"cExample.h"
}

int main(int argc, char* argv[])
{
    add(
2,3); 
    
return 0;
}

//如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern "C" { }。




//2.在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。
//C引用C++函数例子工程中包含的三个文件的源代码如下:

//C++头文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif

//C++实现文件 cppExample.cpp
#include"cppExample.h"
int add( int x, int y )
{
    
return x + y;
}


/* C实现文件 cFile.c
/* 这样会编译出错:#include"cExample.h" 
*/

extern int add( int x, int y );
int main( int argc, char* argv[] )
{
    add( 
23 ); 
    
return 0;
}



volatile
由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化,当某个值被优化时,程序可能只访问寄存器中的拷贝,这时,其它线程对内存中的值进行的修改,不会影响到前面程序从寄存器中读到的值,程序的运行结果就会出现错误。
使用volatile关键字声明的变量不会被编译器进行优化,因为它表示可能被其它原因修改,比如其它线程。


static
1.在固定的地址上分配,也就是说对象是在一个特殊的静态数据区上创建的,而不是每次函数调用时在堆栈上产生的。这也是静态存储的概念。
2.对一个特定的编译单位来说是本地的,这里static控制名字的可见性,所以这个名字在这个单元或类之外是不可见的。
在文件范围内,一个被明确声明为static的对象或函数的名字对编译单元来说是局部变量;这些名字有内部连接。
这意味着我们可以在其他的编译单元中使用同样的名字,而不会发生名字冲突。

#include <iostream>

using namespace std;

//static的两种基本的含义:
//1.在固定的地址上分配,也就是说对象是在一个特殊的静态数据区上创建的,而不是每次函数调用时在堆栈上产生的。这也是静态存储的概念。
int SaveTime()
{
    
static int iTime;        //只在函数第一次调用时初始化一次.
                            
//如果说没有为一个预定义类型的静态变量提供一个初始值的话,编译器也会确保在程序开始时它被初始化为零.
    iTime++;
    
return iTime;
}


class X    {
public:
    X(
const char* c);
    
~X();
private:
    
char* m_c;
}
;

X::X(
const char* c = "Default")
{
    m_c 
= new char[strlen(c)+1];
    strcpy(m_c,c);
    cout
<<"Construct: "<<m_c<<endl;
}


X::
~X()
{
    cout
<<"Destruct: "<<m_c<<endl;
    delete []m_c;
}


void TestX()
{
    
static X x("static");
}


X x(
"Global");

void main()
{
    cout
<<"Enter Main"<<endl;
    TestX();
    
for(int i=0; i<5++i) {
        SaveTime();
    }

    cout
<<SaveTime()<<endl;
    cout
<<"Leave Main"<<endl;
}





const
1、声明变量只读。
2、const 变量必须被初始化。
3、定义常量。
const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。
由于const定义常量从汇编的角度来看,只是给出了对应的内存地址, 而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。
4、类中的const数据成员。
const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么。
const数据成员的初始化只能在类的构造函数的初始化表中进行。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现。枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。
5、修饰类成员函数。
一般放在函数体后,任何不会修改数据成员的函数都因该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其他非const成员函数,编译器将报错,这大大提高了程序的健壮性。
const对象优先调用同名的const成员函数,实现了const重载。
6、修饰函数参数和返回值。
const通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数本就不需要保护,所以不用const修饰。
返回值用const修饰可以防止允许直接对函数结果进行赋值。
posted on 2009-05-27 16:37 大胖 阅读(382) 评论(0)  编辑 收藏 引用 所属分类: C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理