1.分析下述程序:
#include<iostream>
using namespace std;
int main() {
intc=23;
printf("%d\n",c&c);
return0;
}
分析:&是位与运算符,将前后两个数对应相与。任何数与自身相与,保持不变。
(&:同时取1才为1;|:至少有一个1才取1)
2.分析下述程序
#include<iostream>
using namespace std;
class A {
A() {
printf("A()");
}
public:
staticA &get() {
staticA a;
returna;
}
};
int main() {
A::get();
return0;
}
分析:调用静态函数本身不会执行构造函数,但get()实例化了一个对象,所以在get()里面调用了构造函数。
这个代码考察的是单例模式,其中构造函数是私有函数。要想获得A的对象只能通过get()函数。(构造函数默认是私有函数)
调用静态函数不会执行构造函数。但是静态函数里面有引用对象,所以会调用构造函数。
3.构造函数可以设置默认的参数;
构造函数在定义类对象的时候自动执行;
构造函数可以是内联函数;(析构函数也可以内联)
构造函数可以重载;(析构函数不可以重载)
构造函数可以有多个且可以带参数,而析构函数只能有一个,且不能带参数。
只要是类的成员函数,都可以放在类内定义,类内定义的函数,编译器一般看做内联。
4.实现运行时的多态性要使用:虚函数。
分析:多态有静态多态(编译时)和多态多态时(运行时),
静态多态注意实现了函数重载和运算符的重载,动态多态主要实现了虚函数。
5.分析下列程序:
#include<iostream>
using namespace std;
class A {
public:
~A() {
cout<<"~A()";
}
};
class B {
public:
virtual ~B() {
cout<<"~B()";
}
};
class C:public A,public B{
public:
~C(){
cout<<"~C";
}
};
int main() {
C*c=new C;
B*b1=dynamic_cast<B *>(c);
A*a2=dynamic_cast<A *>(b1);
deletea2;
return0;
}
答案解析:创建一个类对象c,然后动态类型转换,让一个B *b1指针指向c,再一次动态类型转换,让一个基类A *a2指针指向b1,当deletea2时,调用析构函数,但是基类A的析构函数不是虚函数,所以只调用A的析构函数,结果应该是:~A()
main()函数中,第一句只用了new,调用了构造函数,没用delete,不会调用析构函数,内存泄露。第二句、第三句只是定义了指向不同对象的指针,不会产生对象,所以构造函数、析构函数都没调用,最后一句delete调用析构函数,因为基类A的析构函数不是虚函数,所以只调用A的析构函数,输出:~A(),如果A的析构函数加上virtual, 输出:~C()~B()~A(),与直接delete c输出一样。 析构函数声明为虚函数,这样析构时,先调用派生类的析构函数,再调用基类的析构函数,防止内存泄露。
6.switch(表达式\变量) {
case 整数常量;
break;
}
7. A.explicit关键字强制仅有显式调用有效,正确,C++提供关键字explicit,用于阻止不应该允许的经过转换构造函数进行的隐式转换的发生。声明为explicit的构造函数不能在隐式转换中使用。
B.保护成员可以在定义它的类中使用,也可以在派生类中使用,正确。保护类就是为了继承产生的
C.保护成员仅可以在定义它的类中使用。错误,见B
8.已知fun(int)是类Test的公有成员函数,p是指向成员函数fun()的指针,采用p=&Test::fun是正确的。
分析:获取非成员函数的地址时,符号&是可选的‘获取成员函数的地址时,符号&是必选的。
9.字长为6位的二进制有符号,其最小值为:-32.
分析:如果是无符号数,它6位都参与预算,111111代表的0到正63,如果是有符号数,最高位当成符号位,不参与运算,从0 00000到0 11111是0到31,而从100001 到111111为负1到负31,中间有一个1 00000本意表示负零,,但是负零和正零都表示零,重复了。所以计算机规定把1 00000表示-32。
6位无符号表示:0~2^6-1,即0~63;
有符号表示范围:-32~31;
10.static修饰的变量只初始化一次,当下一次执行到这一条语句的时候,直接跳过。static存放在data段,函数调用后这块内存不会被销毁,所以i的值增大。
11.x为整型,请用位运算实现x%8: x&7
分析:当我们求余的时候,相当于除以2的N次冥,也就是相当于把数本身右移N位,但是右移掉的那些位需要通过位运算进行保留;用以上例子来说,X%8即X%2^3,那么就需要右移三次,那么移去的三位需要保留下来,而8=1000,刚好,可以使用0111来保留下来后三位,于是,对于除数都是2的整数次幂的情况,可以使用x&(2^n-1)的方法进行与运算,保留下来的最末尾的n位就是余数。该题中,结果为x&7.
补充:
(1) 取模运算转化成位运算 (在不产生溢出的情况下)
a % (2^n) 等价于 a & (2^n - 1)
(2)乘法运算转化成位运算 (在不产生溢出的情况下)
a * (2^n) 等价于 a<< n
(3)除法运算转化成位运算 (在不产生溢出的情况下)
a / (2^n) 等价于 a>> n
例: 12/8 == 12>>3
(4) a % 2 等价于 a & 1
(5) if (x == a) x= b;
else x= a;
等价于 x= a ^ b ^ x;
(6) x 的 相反数 表示为 (~x+1)
点击打开链接 《位运算总结 取模 取余》