基础知识2

来源:互联网 发布:自然灾害数据库 编辑:程序博客网 时间:2024/05/15 00:32

1、一棵树转换为二叉树。
将一棵树转换成二叉树的规则如下: (1)在所有的兄弟结点之间加一条线; (2)对于每个结点,除了保留与长子的连线外,去掉该结点和其他孩子的连线,则根据以上两个规则,我们得到转换后的二叉树为(从此图我们可以得到,将一棵普通树转换成二叉树后,其对应的二叉树的右子树为空):
这里写图片描述
这里写图片描述

2、指出下面代码运行后,指出输出的字符,和代码不合理的地方。

#include <stdio.h>#include <iostream>using namespace std;class A{public:        A(){print2();}        void print1()        {            cout<<"A1"<<endl;        }        virtual void print2()        {            cout<<"A2"<<endl;        }};class B:public A{    private:        int x;    public:        B(){cout<<"B"<<endl;}        void print1()        {            cout<<"B1"<<endl;        }        virtual void print2()        {            cout<<"B2"<<endl;        }};int main(){    B *pb;    A *pa;    pa = new B;//1    pa->print1();//2    pa->print2();//3    pb = (B*)pa;    delete pa;    pb->print1();//4    pb->print2();//5    return 0;}

答案:
A2
B
A1
B2
B1
解析;
考察多肽。
1)A2、B是考察构造函数的顺序。在1处发生。
2)A1在2处发生,因为类的多肽性,非虚函数,是会选择
执行指针所指基类里的函数。
3)B2在3处发生,因为类的多态性,虚函数选择执行子类
里的。
4)B1在4处发生。因为指针已经是B类型的了,所以执行子类。
5)5处这里会使得程序崩溃掉。如果没有delete pa这句话,就
一切正常了。下面是解析:

1)首先要知道delete是删除指针指向的对象,让其释放内存。指针中的地址不变,所以一般在delete指针后,要将该指针的值赋值NULL(置空)。2)其次要知道,不管pa和pb是什么类型的指针,他们里面肯定的,它只会直接去释放掉他们内容所指的地址,所以说这时候的B对象已经被释放了。

http://www.cnblogs.com/malecrab/p/5572730.html
这是虚函数实现的基本原理,可以看见,执行虚函数的时候,实际是通过虚函数表找到虚函数指针,而虚函数指针是在构造函数的时候初始化的,也就是说,实际上对象里是存在其他我们看不见的成员变量,虚函数指针的存在的,所以说在delete的时候,它也会被释放掉,同其他数据成员一样,虚函数的执行方法和普通成员函数是不同的,普通成员函数的执行对应代码段,没有涉及数据成员,所以正常输出了,如果是输出B对象的数据成员x会是随机数。虚函数指针内容既然已经被释放,调用被释放了的指针肯定会出问题的。

3、请问下面代码输出什么?

#include<stdio.h>#include<iostream>using namespace std;struct st_t{    int k;    int status;    int p;    short p2;    short* pdata;    char errstrt[32];};int main(){    st_t st[16];    char *p = (char*)(st[0].errstrt+32);    printf("%d\n",(p-(char*)(st)));    short* pdata2 = (short*)(&(st[0].p2));    printf("%d\n",pdata2-(short*)(st));    char *p2 = &(st[0].errstrt[0]);    printf("%d\n",p2-(char*)(st));    return 0;}

答案:
52
6
20
解析:
结构体的第一个元素地址就是结构体st地址。
使用指针相减的办法算差值,实际上算的差值要在根据指针类型
进行换算,比如实际上两个变量地址差值为32,如果使用的是int指针,
那么计算结果就是1,如果用的是char指针,计算结果就是4。

4、下面的自加自减运算中哪个是错的。
A:a+=(a++);
B:a+=(++a);
C:(a++)+=a;
D:(++a)+=(a++);

答案:
C自加运算不能放在左侧。

5、关键字static的作用
答案:
1)设置变量存储域,函数体内的static变量的作用范围为该函数体,不同于auto变量,
该变量的内存只被分配一次,因此其值在下次调用的时候仍然维持上次的值。
2)限制变量作用域,在模块内一个static 全局变量,可以被模块内的其他函数所访问,
但是不能被模块外的函数访问。
3)限制函数的作用域,在模块内声明的static函数,只可以被模块内的其他函数调用,
它的作用域被限制在声明它的模块内。
4)在类中,static成员变量被所有实例所共享,也就是说某个类的实例化成员修改了这个
静态成员变量,那么其他实例都可见。
5)类中的static成员函数,属于整个类所拥有,这个函数不接收this指针,因而不能访问
类的非静态成员。
关于static成员函数具体还有以下:
.静态成员函数的地址可用普通函数指针储存,而普通成员函数地址需要用 类成员函数指针来储存。举例如下:
class base{
static int func1();
int func2();
};

int (*pf1)()=&base::func1;//普通的函数指针
int (base::*pf2)()=&base::func2;//成员函数指针
指针详细用法:http://blog.csdn.net/lishuhuakai/article/details/18276477

2.静态成员函数不可以调用类的非静态成员。因为静态成员函数不含this指针。

3.静态成员函数不可以同时声明为 virtual、const、volatile函数。举例如下:
class base{
virtual static void func1();//错误
static void func2() const;//错误
static void func3() volatile;//错误
};

下面是示例代码:

#include<stdio.h>#include<iostream>using namespace std;class A{public:    void D()    {        cout<<x<<endl;    }    static void C()    {        cout<<"C"<<endl;    }    static void B()    {        cout<<"B"<<endl;        C();    }    int x = 9;};int main(){    void (*p1)() = &A::C;    A a;    void (A::*p2)() = &A::D;    p1();    (a.*p2)();    return 0;}

6、简述什么是C++友元,其优点和缺点
答案:
C++中,定义一个类中的成员分为私有成员、受保护成员和公有成员,我们知道,这些私有成员和受保护的成员是无法通过对象直接访问的,而是要通过调用公有成员函数从而间接的访问这些私有成员,那假如我的程序中出现循环要重复访问这个私有成员时,每次都要先通过调用公有成员间接的来访问该私有成员,这将造成空间和时间上的大大浪费。
所以,我们就想怎么样能够使对象直接访问这些私有成员呢?那我们就引入了友元这个概念,假设定义了一个A类,又定义了一个B类,如果我们想使B中的某个函数f1可以直接访问A类中的私有成员,那我们就在该函数f1的前面加上friend。
嘿嘿 废话比较多 只是想让你更加深入的了解友元。
如果让我说优缺点的话(用我的话来说):
(1)优点:可以使定义为友元函数或者友元类的函数直接访问另一个类中的私有成员和受保护成员,提高效率,方便编程。
(2)缺点:破坏了类的封装性,提供了安全漏洞

7、多重继承如何消除向上继承的二义性
虚继承详解:http://c.biancheng.net/cpp/biancheng/view/238.html
虚拟继承方式:http://www.2cto.com/kf/201302/191527.html
用父类名方式:http://c.biancheng.net/cpp/biancheng/view/2210.html

8、参数传递方式有几种?__stdcall和__cdecl的区别?
9、什么是回调函数,它有什么作用?
10.简述MFC窗口创建过程
11.如何保证系统只有一个实例在运行
12.varchar类型和char类型比较
13.使用递归的方式累加1-100
14.题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点,链表结点定义如下:

struct ListNode{    int m_nKey;    ListNode* m_pNext;}
0 0