1、 通过封装,对象的全部属性和操作结合在一起,形成一个整体;

通过封装,一个对象的实现细节被尽可能地隐藏起来;(不可见)

通过封装,每个对象都成为相对独立的实体;


2、 数值型常量有整型常量,实型常量,不论是整型常量还是实型常量都有正值和负值之分;


在C语言的预编译处理中,可以用符号名代表一个常量,定义时不必指定常量类型;


常量的定义就是常量是在程序运行过程中值不能够被改变的量;


3、下列程序的输出结果:72.

#include<iostream>
#include<cstdlib >
using namespace std;
 
int main() {
         char a=101;
         int sum=200;
         a+=27;sum+=a;
         cout<<sum<<endl;
}





分析:char类型的范围是-128---+127,当a+=27,之后a的值超出可表示范围会变为-128.

a为char型,-128~127,a=101,a+=27后溢出a=-128:

a=127时不溢出 01111111(127补码)

a+=1时溢出 10000000(-128补码)


sum += a;

sum为int型,a(char提升为int)

10000000------->11111111  11111111  11111111  10000000(-128补码)

所以,sum=200-128:00000000  00000000 00000000  11001000

+11111111 11111111  11111111 10000000

----------------------------------------------------------------------------------

 00000000  00000000  00000000  01001000  (64+8=72)


3、 具有相同类型的指针类型变量p与数组a,不能进行的操作是:D


A p=a;// a表示数组a的地址指针,a和p类型相同,所以p=a操作正确;


B *p=a[0];//*p表示p指向的值,a[0]表示数组的第一个值,两者类型相同,可赋值,正确;


C p=&a[0];//&a[0]是数组第一个元素的地址,与a相同,也是指针,可赋值,正确;


D p=&a;// 设数组a[3],指针为int *p,a本身是一个指针,而&a的类型int(*)[3],而不是int *,但p不一定是int型的,所以p=&a错误。


数组名是一级指针,数组地址为二级指针。


4、有一个类A,其数据成员如下:

class A {
         ……
         private:
                   int a;
         public:
                   const int b;
                   float* &c;
                   static const char * d;
                   static double *e;
};




则构造函数中,成员变量一定要通过初始化列表来初始化的是: b,c、  (此处可以参考学习点击打开链接


分析:构造函数初始化时必须采用初始化列表一共有三种情况:

1).需要初始化的数据成员是对象(继承时调用基类构造函数);

2).需要初始化const修饰的类成员;

3).需要初始化引用成员数据;


因为static属于类并不属于具体的对象,所以 static成员是不允许在类内初始化的,那么static const 成员是不是在初始化列表中呢?

答案是NO

一是static属于类,它在未实例化的时候就已经存在了,而构造函数的初始化列表,只有在实例化的时候才执行。

二是static成员不属于对象。我们在调用构造函数自然是创建对象,一个跟对象没直接关系的成员要它做什么呢。


分析二:初始化:从无到有,创建了新对象;如:string foo = "HelloWorld!"

赋值:没有创建新对象,而是对已有对象赋值。如:string bar; bar = "Hello World!"


有时我们可以忽略数据成员初始化和赋值之间的差异,但并非总能这样。

如果成员是const或者是引用的话,必须将其初始化。类似的,当成员属于某种类类型且该类没有定义默认构造函数时,也必须将这个成员初始化。(比如:类A中有一成员是B b,但类B中没有定义默认构造函数时,就必须对A中b成员进行初始化)


随着构造函数体一开始执行(即大括号里面部分),初始化就完成了(构造函数体内只是赋值操作)。因此,上面三种情况,比如初始化const或者引用类型的数据成员的唯一机会就是通过构造函数初始值,形如:ConstRef::ConstRef(int n): i(n), j(n) { }


5、存在性就是变量生命周期。可见性就是能访问。内部静态类就是只有在包含该类的上下文里才能使用的类,比如在一个类内部定义的类,但它是全局存在的。因此内部静态类的可见性和存在性不一致。

6、转义字符的定义为:所有的 ASCII码都可以用“\”加数字(一般是8进制数字)来表示。而C中定义了一些字母前加"\"来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等,就称为转义字符,因为后面的字符,都不是它本来的ASCII字符意思了。


7、对下述代码执行后,会出现:数组越界问题。

charszMsisdn[MAX_LEN_MSISDN-1]; //建立一个长度为MAX_LEN_MSISDN-1的数组,下标范围应为0~MAX_LEN_MSISDN-2
szMsisdn[sizeof(szMsidn)='\0']; //sizeof(szMsidn)得到的是数组长度,为MAX_LEN_MSISDN-1,那么szMsisdn[sizeof(szMsidn)]= szMsisdn[MAX_LEN_MSISDN-1]/				//,很明显数组越界了


8、testArray是一个包含8个元素的int型数组,请问sizeof(testArray)/sizeof(testArray[0])=8、

分析:sizeof(testArray)是数组大小8*4=32;
sizeof(testArray[0])是testArray[0]的大小4;
所以sizeof(testArray)/sizeof(testArray[0])=8


#include<iostream>
#include<cstdlib>
using namespace std;
int main() {
         inttestArray[8]={0};
         cout<<sizeof(testArray)/sizeof(testArray[0]);
}


9、

#include<iostream>
#include<cstdlib>
using namespace std;
int main() {
         char*a[]={"work","at","alibaba"};
         char**pa=a;
         cout<<pa<<endl;
         cout<<*pa<<endl;
         cout<<**pa<<endl;
        
         pa++;
         cout<<*pa<<endl;
}



打印结果:

0x22fe30

work

w

at

分析:首先对编译器来说没有数组这一概念,数组都被看成指针,所以a[]就是*a,那么就是**a换成了**pa,pa即是a,换个名字而已,根据数组的++,也就是取a[1][]的值,即“at”。

 

C++学习(19)_数组

数组里存储的是指针;
而我们创建的变量pa相当于指向指针的指针是一个二级指针;
所以我们联系之前所学的内容,其实呢就是pa指向了数组的首元素,++一次使得其指向下一个元素。