C++学习(22)

来源:互联网 发布:通用后台管理系统源码 编辑:程序博客网 时间:2024/04/30 00:53

1、 凡是函数中未指定存储类别的局部变量,其隐含的存储类别为:auto(自动)


2、定义符号常量pi. Const float pi=3.1415926f;(正确)


3、  C语言长整型数值在计算机中占用字节数是:4

分析:一般我们把 short称为短整型,把 long称为长整型,把 long long称为超长整型,把 int称为整型。unsigned打头的那些整数类型统称为无符号整型。例如:我们称 unsigned short为无符号短整型。以此类推。

不管是16位系统还是 32 64位系统,sizeoflong)都等于4

 

4、 程序中,允许用typedef来说明一种新的类型名;

使用typedef说明新类型名时,其格式是:typedef新类型名原类型名;

在使用typedef改变原类型的名称后,可以使用原来或新的类型名;

 

5、派生类构造函数执行的次序

1)调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左到右)

2)对派生类新增的成员对象初始化,调用顺序按照它们在类中声明的顺序

3)执行派生类的构造函数体中的内容

 

6分析下述代码的打印结果:

#include<iostream>#include<string.h>using namespacestd; int main(){       int n[][3]={10,20,30,40,50,60};       int (*p)[3];       p=n;       cout<<p[0][0]<<","<<*(p[0]+1)<<","<<(*p)[2]<<endl;       return 0;}

分析:p[0][0]指的是第一个元素;
p[0]+1指的是第一行第二个元素;
(*p)[2]数组指针,表示第一行的第三个元素;
**(p+1)表示第二行第一个元素;

 

a[3]声明的是一维数组,则(*p)[3]也是一维数组,只不过p为指向二维数组的指针,p=n,则:
p[0][0]=n[0][0]=10
*(p[0]+1)=n[0][1]=20
(*p)[2]=*(*(p+0)+2)=n[0][2]=30

 

一维数组:

a <=>&a[0] a+1 <=> &a[1]

*a <=> a[0]  *(a+1) <=> a[1]

二维数组:

a[0] <=>&a[0][0]a[1] <=> &a[1][0] a[1]+1 <=> &a[1][1]

*a[0] <=>a[0][0] *a[1] <=> a[1][0] *(a[1]+1 )<=> a[1][1]

 

7print()函数是一个类的常成员函数,它无返回值,下列正确的是(C

A const void print();          Bvoid const print();

C void print() const;        D void print(const);

分析:const voidprint(const int num)const第一个const修饰返回类型第二个const修饰参数第三个const修饰调用对象

 

const修饰类的成员函数,一般放在函数体后,如 void fun() const;

常成员函数声明:形如 void funcName(参数表) const;

对于常成员函数需要注意:

1)、其实现部分也要带const关键字;

2)、不能修改类的成员变量,不能调用类中没有被const修饰的成员函数(即只能调用常成员函数);

 

8分析下述代码的打印结果:

#include<iostream>#include<string.h>using namespace std;class A {       public:              virtual void func(int val=1) {                     std::cout<<"A->"<<val<<std::endl;              }              virtual void test() {                     func();              }}; class B:public A {       public:              void func(int val=0) {                     std::cout<<"B->"<<val<<std::endl;              }};int main(){       B *p= new B;       p->test();       return 0;}

记住:virtual函数是动态绑定,而缺省参数值却是静态绑定。意思是你可能会 在“调用一个定义于派生类内的virtual函数”的同时,却使用基类为它所指定的缺省参数值

 

结论:绝不重新定义继承而来的缺省参数值!(可参考《Effective C++》条款37

对于本例:

B*p =newB;p->test();

p->test()执行过程理解:

(1)由于B类中没有覆盖(重写)基类中的虚函数test(),因此会调用基类A中的test()

(2)Atest()函数中继续调用虚函数 fun(),因为虚函数执行动态绑定,p此时的动态类型(即目前所指对象的类型)为B*,因此此时调用虚函数fun()时,执行的是B类中的fun();所以先输出“B->”;

(3)缺省参数值是静态绑定,即此时val的值使用的是基类A中的缺省参数值,其值在编译阶段已经绑定,值为1,所以输出“1”;

最终输出“B->1”。所以大家还是记住上述结论:绝不重新定义继承而来的缺省参数值!

 

9分析下述代码的打印结果:

#include<iostream>#include<string.h>using namespace std;int main(){       char*a[]={"hello","the","world"};       char**pa = a;             cout<<*pa<<endl;       cout<<pa<<endl;       cout<<**pa<<endl;             pa++;       cout<<*pa<<endl;       cout<<pa<<endl;       cout<<**pa<<endl;       return0;} 

分析:a是指针的数组。
char**p=a;//char **p=&a[0]
p++;//p是指针自增+4,而a中元素是指针,每个正好四个字节,因此p++后恰好p=&a[1] ,*p=a[1];输出"the",


分析二:

char *a[]={"hello","the","world"};
//定义了一个char型指针数组即字符串指针,分别指向“hello”,“the”,“world”
char**pa=a;//定义了一个char型二级指针,指向一个指针数组
pa++;//二级指针偏移,指向“the”
因此*pa输出the

 

10友元函数重载运算符时,因为没有this指针指向对象,因此参数个数保持和原来一样,运算符至少有一个参数;

友元函数重载时,参数列表为1,说明是1元,为2说明是2元;

成员函数重载时,参数列表为空,是一元,参数列表是1说明为2元;

 

11、分析下述代码的打印结果:

#include<iostream>#include<string.h>using namespace std;int main(){       short*p,*q;       shortarr[15]={0};       p=q=arr;       p++;       cout<<p-q<<endl;       cout<<(char*)p - (char *)q<<endl;       cout<<sizeof(arr)/sizeof(*arr)<<endl;       return0;}

分析: 指针自增、自减每次移动的偏移量是指针所指向对象的字节大小,所以p++与q的偏移量是2个字节。

指针相减的值是指针地址的偏移除以指针每次移位的大小

1)p-q=1;偏移量为2个字节,每次移动2个字节,所以为2/2=1;

2)(char *)p-(char*)q,指针的偏移没变,但是每次指针移位是按照(char*)类型移动,即每次移动1个字节,所以是2/1=2

3)数字每个元素2个字节,所以sizeof(arr)表示为数组所有元素的字节个数15*2=30,而sizeof(*arr)表示为数组第一个字符所占的大小为2个字节,所以30/2=15

 

分析二:两个指针变量之间的运算,只有指向同一数组的两个指针变量之间才能进行运算,否则运算毫无意义。

1) 两指针变量相减

两指针变量相减所得之差是两个指针所指数组元素之间相差的元素个数实际上是两个指针值(地址)相减之差再除以该数组元素的长度(字节数)。例如pf1pf2是指向同一浮点数组的两个指针变量,设pf1的值为2010Hpf2的值为2000H,而浮点数组每个元素占4个字节,所以pf1-pf2的结果为(2000H-2010H)/4=4,表示pf1 pf2之间相差4个元素。

注意:两个指针变量不能进行加法运算。例如,pf1+pf2是什么意思呢?毫无实际意义。

2) 两指针变量进行关系运算

指向同一数组的两指针变量进行关系运算可表示它们所指数组元素之间的关系例如:pf1==pf2表示pf1pf2指向同一数组元素;pf1>pf2表示pf1处于高地址位置;pf1<pf2表示pf2处于低地址位置。

指针变量还可以与0比较。设p为指针变量,则p==0表明p是空指针,它不指向任何变量;p!=0表示p不是空指针。

空指针是由对指针变量赋予0值而得到的。例如:#define NULL 0 int *p = NULL;

对指针变量赋0值和不赋值是不同的。指针变量未赋值时,值是随机的,是垃圾值,不能使用的,否则将造成意外错误。而指针变量赋0值后,则可以使用,只是它不指向具体的变量而已。

 

关于此处的学习可以参考:点击打开链接


12

int相关的类型在不同位数机器的平台下长度不同。C99标准并不规定具体数据类型的长度大小,只规定级别。作下比较:

 

116位平台

char 1个字节8

short 2个字节16

int 2个字节16

long 4个字节32

指针 2个字节16

 

232位平台

char 1个字节8

short 2个字节16

int 4个字节32

long 4个字节32

long long 8个字节64

指针 4个字节32

 

364位平台

char 1个字节 

short 2个字节

int 4个字节

long 8个字节(区别)

long long 8个字节

指针 8个字节(区别)


13private成员只能在当前类中访问,派生类可以访问父类的publicprotected属性成员

数据成员和函数成员默认是default访问权限,同一个包下的所有类都可以访问

B不一定和类A同包;

 

14heap&stack区别

1.heap是堆,stack是栈。

2.stack的空间由操作系统(不是编译器)自动静态分配和释放(进站和出栈可控);heap的空间是手动申请和释放的,heap常用new关键字来动态分配(—“内存泄露”—— Memory Leak

3.stack空间有限(经常有栈溢出,而不是堆溢出),heap的空间是很大的自由区。

Java中,若只是声明一个对象,则先在栈内存中为其分配地址空间,若再new一下,实例化它,则在堆内存中为其分配地址。

4.举例:

数据类型变量名;这样定义的东西在栈区。

如:Object a =null;只在栈内存中分配空间

new 数据类型();或者malloc(长度);这样定义的东西就在堆区

如:Object b =new Object();则在堆内存中分配空间

 

补充:

栈:Windows,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在Windows下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。

 

堆:为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。


可以参考点击打开链接进一步学习!!!

原创粉丝点击