1、
对于int a[10],定义的数组包含10个元素,对数组元素引用的下标是从0~9。显然a[10]超出了数组的范围
2、
对于0x122,C/C++规定,16进制数必须以 0x开头;
因此122 = 1*16^2+2*16+2 = 290
3、char str[]=“xunlei”;
char str2[]={‘x’,‘u’,‘n’,‘l’,‘e’,‘i’};
//sizeof(str)计算’\0’,sizeof(str2)不计算’\0’
所以sizeof(str)=7,sizeof(str2)=6
4、while(i++<7) { 语句1 }可以写成:
while(i<7){
i++;
if…
}
5、struct S a[3]={{3,“abc”},{5,“def”},{7,“ghi”}};
p=a;
p中存放a的地址(相当于首元素地址)
A:++p相当于加到a[1],(++p)->n == 5
B:a为首元素地址,+1,相当于加到a[1],(a+1)->n == 5
C:p后++,这时p还是在a[0],p+±>n ==3
D:p+1相当于加到a[1],(++p)->n == 5
6、int i=10, *p=&i; *p =&i等价于 p=&i;*p=i
7、多重继承图示:(以左边为例)
-
多重继承定义: 一个派生类(D)有2个或2个以上的基类(B和C);
-
多重继承引起的二义性: 假如上述这些基类(B和C)具有相同的基类A,A中的成员数据和成员函数,最终都会以双份的形式拷贝到类D中,
那么调用的时候就会出现二义性问题。 -
虚基类: 专门用来解决多重继承引起的二义性问题;(可以理解为D直接从A继承)
8、指针类型总是和int类型长度一致,int 在32位就是4,在64位就是8
9、
a+sizeof(int),等价于a[4]的地址,因为数组a为int型,步长为4,+1就相当于向前进了4字节,等于a[1]地址,+4相当于进了16字节,等于a[4]地址
10、拷贝构造函数和拷贝赋值函数注意点
#include<iostream>
using namespace std;
class MyClass
{
public:
MyClass(int i = 0)//构造函数
{
cout << i;
}
MyClass(const MyClass &x)//拷贝构造函数
{
cout << 2;
}
MyClass &operator=(const MyClass &x)//拷贝赋值函数
{
cout << 3;
return *this;
}
~MyClass()//析构函数
{
cout << 4;
}
};
int main()
{
MyClass obj1(1), obj2(2);
MyClass obj3(obj1);//情况1
// MyClass obj3 = obj1;//情况2
//下面的是情况三
// MyClass obj3;
// obj3 = obj1;
return 0;
}
- 情况1输出:
- 情况2输出:
- 情况3输出
11、
题目
12、
C++ Primer说到:int,short,long都是signed的;char可能是signed的,也可能是unsigned的;
13、
#include <stdio.h>
main()
{
int x, y;
scanf("%2d%*4s%2d",
&x, &y);
printf("%d",
y-x);
}
输出结果为:78-12=66
注:将输入的前两位给x,跳过中间的四个字符,将之后的两位给y。所以x=12,y=78.
14、
#include <iostream>
using namespace std;
class Base {
public:
Base(int j): i(j) {}
virtual~Base() {}
void func1() {
i *= 10;
printf("%d\n",1);
func2();
}
int getValue() {
return i;
}
protected:
virtual void func2() {
printf("%d\n",2);
i++;
}
protected:
int i;
};
class Child: public Base {
public:
Child(int j): Base(j) {}
void func1() {
printf("%d\n",3);
i *= 100;
func2();
}
protected:
void func2() {
printf("%d\n",4);
i += 2;
}
};
int main() {
Base * pb = new Child(1);
pb->func1();
cout << pb->getValue() << endl;
delete pb;
return 0;
}
(解释:基类的指针指向派生类的对象,基类指针调用其虚成员函数,
则会调用其真正指向对象的成员函数,而不是基类中定义的成员函数,
若不是虚函数,则不管基类指针指向的是哪个派生对象,调用的都是
基类中定义的那个函数 )
上诉代码中的1,2,3,4是为了验证有没有调用该函数
输出见下图:
15、
overload是重载,一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同。
重载的规则:
1、在使用重载时只能通过相同的方法名、不同的参数形式实现。不同的参数类型可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不一样);
2、不能通过访问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
16、
为避免运算过程中出现整型溢出可以考虑的办法有
1、检测符号位的变化
2、将计算结果减去加数看是否与另一加数相等
17、
int (*s[10])(int) 表示的是什么?
1、首先*s[10] 是一个指针数组,s 是一个含有10个指针的数组,故可以这样来看这条声明语句:假设 p 等价于 s[10],声明语句变为 int (*p)(int);
2、观察 int (*p)(int), 从名字开始,p前面有一个 * ,因此 p 是指针,有侧是形参列表,表示p指向的是函数,在观察左侧,函数返回的是 int;
3、则 int (*p)(int) 解读为:函数指针,指向一个 int func(int param) 的函数;
4、故 int (*s[10])(int) :解读为:函数指针数组,每个指针指向一个 int func(int param)的函数。
18、
指针变量是用来指示一个内存地址的变量,因此只能将地址赋给指针变量,而不能是整数或浮点数
整数通过强制类型转换后可赋值给指针变量, 要注意转换后的类型要和指针指向的类型一致,并且这个整数的位长不能超过指针的位长
19、
int a = 0;
int b = (a=-1) ? 2:3;
int c = (a=0) ? 2:3;
输出为:b=2, c=3
a=-1,表达式的值为-1,非零,为真,故b=2;
a=0,表达式的值为,为零,为假,故c=3;
20、
21、
22、
23、
封装:可以隐藏细节,使得代码模块化
继承:可以拓展已经存在的代码模块类
封装和继承都是为了代码的重用,而多态为了另外一个目的——接口重用
多态:就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
而重载是属于多态的一类
24、
class A
{
public:
A()
{
printf("1");
}
A(A &a)
{
printf("2");
}
A &operator=(const A &a)
{
printf("3");
return *this;
}
};
int main()
{
//下面这种情况输出12
A a;
A b = a;
//下面这种情况输出113
A a;
A b;
b=a;
}
25、
‘\’不是字符
‘\xff’是十六进制表示的字符
'\O00'1到3位表示的八进制字符
26、
抽象类有一下几个特点:
(1)抽象类只能用作其他类的基类,不能建立抽象类对象。
(2)抽象类不能用作参数类型、函数返回类型或显式转换的类型。
(3)可以定义指向抽象类的指针和引用,此指针可以指向它的派生类,进而实现多态性。