1,如果派生类和基类有相同名字的变量,派生类会覆盖基类的变量吗?
class A { int i; };
class B : public class A { int i; };
不会覆盖,只会隐藏,sizeof(A) = 4, sizeof(B) = 8可以证明这一点,隐藏的意思是说通过派生类的对象或指针无法访问基类的变量,实际上,编译器可能会对类的member加上class名称,形成独一无二的命名,这个过程叫做name-mangling, 处理后class B变成:
class B { int i1A; int i1B; } ;
2.为什么static member function不能用const修饰
static void foo() const {} //Error
我们都知道,const函数不能改变对象,那么它是怎样做到这一点的呢?答案是用const修饰this指针,内部转化过程:
void foo() const { } ----------------->void foo(const this) { }, 然而static函数没有this指针,所以也就没必要用const声明了。
3.一句话总结派生类如何利用基类:
我有的东西绝不跟你要,我没有的东西一定跟你要,如果你也没有,就算了。
4.哪些函数是虚函数(virtual function)?
(1).使用virtual关键字声明的: class A { virtual void foo() {} }; 这样的函数是virtual function
(2).从基类继承而来的,且重写(overrided)了:
class A { virtual void foo() {} }; class B : public class A { void foo() {} };
我们说Class B的foo()函数也是virtual function
(3).从基类继承而来的,没有重写:
class A { virtual void foo() {} }; class B : public class A { };
虽然class B没有foo()的定义,但class B有一个virtual function,那就是A::foo(),因为它是从class A继承而来的。
(4)基类的destructor是virtual的
class A { virtual ~A() {} }; class B : public class A { ~B() {} };
我们说class B的destructor也是virtual function
对于所有上述virtual function,编译器都会把它们的首地址保存在一个Virtual Table里面。
注意构造函数不 能是virtual functjion,从实现上来说,调用virtual function需要保证设置好vptr,而调用造函数时这个vptr根本还没初始化,也就不能使用,所以不能把构造函数声明为virtual. 从实际意义来说,调用构造函数意味着想要创建一个类的对象,这个类是确定的,所以它所调用的构造函数也是确定的,故没必要把构造函数变为virtual。
4。满足哪些条件才会重载(overrid)基类的函数
C++标准规定,只有函数名,参数列,返回值类型都相同,才会重写,下列函数都会重载:
void func()-------void func()
virtual void func() ------void func()
void func() ---------virtual func()
virtuan void func() --------virtual void func()
注意这里的返回值支持多态,也就是如果class Derived : public Base那么这个函数也会重写
Base *clone() ---------Derived *clone()
5.以下两个函数有什么区别?
int k = 5;
int *j = k;
void func1( int * i) {}
void func2( int * & i) {}
本质上,两个函数的实参都是一个变量的地址,但有一点微小的却别。
func1的形参类型为int *,那么实参可以为指针变量,也可以为int变量的地址,所以有两种调用方式:
func1( &k );
func1( j );
func2的形参为指针的引用,那么实参必须是指针变量,所以只能这样调用:
func2( j )
6。友元函数的作用是什么?
大多数时候都会把类的data members声明为protected,这样的封装符合面向对象的设计原则,但有些时候我们会很想访问一个对象的protected成员,可以在类里面插入一个友元函数,把它的参数设为类的引用,然后在类的外面定义它,通过参数--对象的引用来访问protected成员。