C++学习(54)

来源:互联网 发布:2016淘宝女鞋店铺排行 编辑:程序博客网 时间:2024/06/16 23:54

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)


点击打开链接 位运算总结 取模 取余》

原创粉丝点击