爱立信面试

来源:互联网 发布:手游防御矩阵攻略 编辑:程序博客网 时间:2024/04/30 07:12
1 构造函数能否是虚函数?
多态:根据对象的动态类型来选择要调用的方法。而在构造函数之前,对象甚至都不存在。
构造函数不能是虚函数,在创建一个对象的时候,构造函数需要的是它要创建的对象的准确的类型,所以不能是虚函数。除此之外,构造函数并不是一般的函数,它跟内存管理的交互方式不同于一般的成员函数,所以不能用指针指向构造函数。
vtable是在构造函数中才初始化的,找不到vtable就不可能调用。
析构函数可以是虚函数,而且常常如此,由于通常通过基类的指针来销毁对象,如果析构函数不为虚的话,就不能正确识别对象类型,从而不能正确销毁对象。
解释:在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。
class   A
{
public:
A();
      virtual   ~A();
};
A::A()
{
}
A::~A()
{
      printf("Delete   class   AP/n");
}

class   B   :   public   A
{
public:
      B();
      ~B();
};

B::B()
{   }
B::~B()
{
      printf("Delete   class   BP/n");
}

int   main(int   argc,   char*   argv[])
{
      A   *b=new   B;
      delete   b;
      return   0;
}

输出结果为:Delete   class   B                  Delete   class   A
如果把A的virtual去掉:那就变成了Delete   class   A
因此在类的继承体系中,基类的析构函数不声明为虚函数容易造成内存泄漏。

2 多重继承构造函数如何?虚拟继承的概念
有可能产生菱形结构,当一个派生类要使用多重继承时,必须在派生类和冒号之后列出所有基类的类名。
菱形结构会有一个模糊问题,不知道应该用哪一个父类的构造函数或者成员函数。
给出的实例是交通工具派生出汽车和船,然后汽车和船共同派生出水陆两用车。

需要虚拟继承技术,当系统碰到多重继承的时候就会自动先加入一个Vehicle的拷贝,当再次请求一个Vehicle的拷贝的时候就会被忽略,保证继承类成员函数的唯一性。
构造水陆两用车的时候,先调用交通工具的构造函数,然后分别按照继承的顺序调用两个父类的构造函数。
class Vehicle
{
    public:
        Vehicle(int weight = 0)
        {
            Vehicle::weight = weight;
cout<<"载入Vehicle类构造函数"<<endl;
        }

        void SetWeight(int weight)
        {
cout<<"重新设置重量"<<endl;
            Vehicle::weight = weight;

        }

        virtual void ShowMe() = 0;
    protected:
        int weight;
};

class Car:virtual public Vehicle//汽车,这里是虚拟继承
{
    public:
        Car(int weight=0,int aird=0):Vehicle(weight)
        {
            Car::aird = aird;
cout<<"载入Car类构造函数"<<endl;
        }
        void ShowMe()
        {
            cout<<"我是汽车!"<<endl;
        }
    protected:
        int aird;

};

class Boat:virtual public Vehicle//船,这里是虚拟继承
{
    public:
        Boat(int weight=0,float tonnage=0):Vehicle(weight)
        {
            Boat::tonnage = tonnage;
            cout<<"载入Boat类构造函数"<<endl;
        }
        void ShowMe()
        {
            cout<<"我是船!"<<endl;
        }
    protected:
        float tonnage;
};
class AmphibianCar:public Car,public Boat//水陆两用汽车,多重继承的体现
{
    public:
        AmphibianCar(int weight,int aird,float tonnage)
        :Vehicle(weight),Car(weight,aird),Boat(weight,tonnage)
        //多重继承要注意调用基类构造函数
        {
            cout<<"载入AmphibianCar类构造函数"<<endl;
        }

        void ShowMe()
        {
            cout<<"我是水陆两用汽车!"<<endl;
        }

        void ShowMembers()
        {
            cout<<"重量:"<<weight<<"顿,"<<"空气排量:"<<aird<<"CC,"<<"排水量:"<<tonnage<<"顿"<<endl;
        }
};
int main()

{
    AmphibianCar a(4,200,1.35f);
    a.ShowMe();
    a.ShowMembers();
    a.SetWeight(3);
    a.ShowMembers();
    system("pause");
}

虚拟继承的主要目的还是为了避免继承机制的二义性。第一种二义性是多个基类同名成员函数产生的,这个时候最好使用域操作符制定想要调用哪一个父类的成员函数。 第二种是多个父类的共同基类产生的二义性,就像上面说的,A是B,C的共同基类,D继承于B,C。也就是菱形的结构,这时候D在构造函数的时候,虚拟继承可以避免对A的两次构造函数调用。

可以说,基类声明的虚函数,在派生类中也是虚函数,即使不再使用virtual关键字。
一个函数声明为纯虚后,纯虚函数的意思是:我是一个抽象类!不要把我实例化!纯虚函数用来规范派生类的行为,实际上就是所谓的“接口”。它告诉使用者,我的派生类都会有这个函数。


3 电梯算法:
假设只有一部电梯,采用的方法是状态机。
电梯可以有三种运行状态,停止,下行或者上行。
电梯的请求分为内部和外部,内部比外部多一个flag相互区分,每一个请求可以是一个map,保存的是请求的层数和请求的内容,即是上还是下。
在电梯停止的时候,优先满足最近层数的请求,无论内部还是外部。
而一旦开始运行之后,根据运行的方向会有一个优先级,假如说是向下运行,那么此时的优先级顺序应该是 近下 远下 远上 近上的顺序。四种状态被标准,可以删除请求或转换请求。
另外电梯在满的情况下需要区分内部和外部请求,只满足内部同向请求。
另外 在前进方向上的请求和背离前进方向的请求应该分别存在两个list里面。

原创粉丝点击