天天看點

C++程式員面試指南第9章

面試題1:指出下段程式的錯誤,并解釋它為什麼是錯誤的。

#include<iostream.h>
class Base
{
public:
int val;
Base()
{
val = 1;
};
};
class Derive: Base
{
public:
int val;
Derive(int i)
{
val = Base::val + i;
};
};


int main(int, char**,char**)
{
Derive d(10);
cout<<d.Base::val<<endl<<d.val<<endl;
return 0;
}
           

答案:class Derive:Base錯誤,因為預設的繼承關系為私有繼承,私有繼承時子類的對象不

能通路父類的成員,導緻cout<<d.Base::val<<endl<<d.val<<endl;出錯,應将class Derive:Base

改為class Derive: public Base。

改正後運作結果:

1

11

面試題2:用C++設計一個不能被繼承的類

答案:

template <typename T> class A
{
friend T;
private:
A() {}
~A() {}
};
 
class B : virtual public A<B>
{
public:
B() {}
~B() {}
};
class C : virtual public B
{
public: 
C() {}
~C() {}
};
void main(void)
{
B b;
//C c;
return ;
}
           

編譯結果:

error C2248: 'A<class B>::A<class B>' : cannot access private member declared in class 'A<class B>'

面試題3:下面說法正确的是那個?

class A
{
virtual void func1() {};
void func2();
};
class B: public virtual A
{
void func1()
{
cout<<"func1 in class B"<<endl;
}
virtual void func2()
{
cout<<"func2 in class B"<<endl;
}
};
           

根據這段代碼,判斷以下說法正确的是:

A:A中的func1和B中的func2都是虛函數。

B:A中的func1和B中的func2都不是虛函數。

C:A中的func2是虛函數和B中的func1不是虛函數。

D:A中的func2和B中的func1都是虛函數。

答案:答案A是正确的。

面試題4:寫出程式的列印結果

#include <iostream.h>
class A
{
public:
virtual void print(void)
{
cout<<"A::print()"<<endl;
}
};
class B:public A
{
public:
virtual void print(void)
{
cout<<"B::print()"<<endl;
};
};
class C:public B
{
public:
virtual void print(void)
{
cout<<"C::print()"<<endl;
}
};
void print(A a)
{
a.print();
}
void main(void)
{
A a, *pa, *pb, *pc;
B b;
C c;

pa = &a;
pb = &b;
pc = &c;

a.print();
b.print();
c.print();

pa->print();
pb->print();
pc->print();

print(a);
print(b);
print(c);
}
           

答案:

A::print()

B::print()

C::print()

A::print()

B::print()

C::print()

A::print()

A::print()

A::print()

面試題5:通路基類的私有虛函數

寫出以下程式的輸出結果

#include <iostream.h>
class A
{
virtual void g()
{
cout<<"A::g"<<endl;
}
private:
virtual void f()
{
cout<<"A::f"<<endl;
}
};
class B:public A
{
void g()
{
cout<<"B::g"<<endl;
}
virtual void h()
{
cout<<"B::h"<<endl;
}
};
typedef void (*Fun)(void);
void main()
{
B b;
Fun pFun;
for(int i = 0; i < 3; i++)
{
pFun = (Fun)*((int*)*(int*)(&b)+i);
pFun();
}
}
           

答案:

B::g

A::f

B::h

面試題6:簡述成員函數的重寫、重載和隐藏的差別

答案:

(1)重寫和重載主要有以下幾點不同。

*範圍的差別:被重寫函數和重寫函數在兩個類中,而重載和被重載函數在一個類中。

*參數的差別:被重寫函數和重寫函數的參數清單一定相同,而被重載函數和重載函數的參數清單一定不同。

*virtual的差別:重寫的基類中被重寫的函數必須要有virtual修飾,而重載函數和被重載函數可以被

virtual修飾,也可以沒有。

(2)隐藏和重寫、重載有以下幾點不同。

*與重載的範圍不同:和重寫一樣,隐藏函數和被隐藏函數不再同一個類中。

*參數的差別:隐藏函數和被隐藏的函數的參數清單可以相同,也可以不同,但是函數名肯定要相同。當參數不

相同時,無論基類中的參數是否被virtual修飾,基類的函數都是被隐藏,而不是被重寫。

面試題7:簡述多态實作的原理

答案:編譯器發現一個類中有虛函數,便立即會為此類生成虛函數表vtable。虛函數表的各表項為指向對應虛

函數的指針。編譯器還會在此類中隐含插入一個指針vptr(對VC編譯器來說,它插在類的第一個位置上)指向

虛函數表。調用此類的構造函數時,在類的構造函數中,編譯器會隐含執行vptr和vtable的關聯代碼,将vptr

指向對應的vtable,将類與此類的vtable聯系了起來。另外在調用類的構造函數時,指向基礎類的指針此時已

經變成指向具體類的this指針,這樣依靠此this指針即可得到正确的vtable。如此才能正确與函數體進行連接配接,

這就是動态聯編,實作多态的基本原理。

繼續閱讀