博文
C++的虚函数(2007-11-18 11:06:00)
摘要:C++的虚函数
一,让我们进入内存——I will come back(阿诺的口头禅)
首先,我觉得了解一个含有虚拟函数的类在内存中的结构是有必要的。
假设一个这样的类:
class CShape
{
int b1;
public:
void MyTest()
{
cout << "CShape::MyTest \n";
}
};
在栈区,它仅仅只是占据了四个字节,用于存放成员数据——b1。
奇怪,那么它的成员函数在那里呢?对于普通的成员函数,编译器采取的是“名字粉碎法”,对于VC++6.0,它将CShape::MyTest()编修改为:“?MyTest@CTestA@@QAEXXZ”,真是个奇怪的名字,但是在这个名字中却保存了重要的信息,比如所属类,参数类型等,具体的大家可以查查相关资料,不好意思,我忘记了。
现在我们讨论虚拟函数, 假设另外的一个类:
class CShape_V
{
int b1;
public:
virtual void play()
{
cout << "CShape::play \n";
}
&nbs......
C++五大内存分区(2007-11-18 10:50:00)
摘要:
C++五大内存分区
在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)
明确区分堆与栈
在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。
首先,我们举一个例子:
void f() { int* p=new int[5]; }
这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,他在VC6下的汇编代码如下:
00401028 push &n......
progma 语法(2007-10-27 18:38:00)
摘要:progma 语法
progma 是一个C语言中的预处理指令,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
其格式一般为: #pragma Para
其中Para 为参数,下面来看一些常用的参数。
(1)message 参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗
口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:
#Pragma message(“消息文本”)
当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法
#ifdef _X86
#Pragma message(“_X86 macro activated!”)
#endif
当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_
X86 macro activated!”。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了
。
(2)另一个使用得比较多的pragma参数是code_seg。格式如:
#pragma code_seg( ["section-name"[,"section-class"] ] )
它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。
(3)#pragma once (比较常用)
只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。
(4)#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。
有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma startup指定编译优先级......
9*9乘法表-3(2007-08-31 20:05:00)
摘要:
# include<iostream.h>
void main()
{
cout<<"*"<<" ";
for(int i=1;i<=9;i++)
cout<<i<<" ";
cout<<endl;
for(int row=1;row<=9;row++)
{
cout<<row<<" ";
for(int j=1;j<=(row-1)*4;j++)//控制空格数
cout<<" ";
for(int col=row;col<=9;col++)
{
if(col*row<10)
cout<<col*row<<" ";
else
cout<<col*row<<" ";
}
cout<<endl;
}
}......
P74 4.3(2007-08-23 20:27:00)
摘要:
P74 4.3
# include<iostream.h>
int cube(int n)//求立方
{
return n*n*n;
}
void main()
{
for(int i=100;i<999;i++)
{
int num=i; //保存i的初值;
int a,b,c;//分别表i的个位,十位,百位
c=num/100; //得到百位
num=num%100;//改变i值为两位数
b=num/10;
a=num%10;
if(cube(a)+cube(b)+cube(c)==i)
cout<<"得到的水仙花数为:"
<<i<<endl;
}
}......