//**************by er lei2009-10-16********************//
声明两个类:
class Base
{
public:
Base()
{
cout<<"Base Init/n";
}
virtual ~Base()
{
cout<<"Base ~~/n";
}
void DoSome()
{
cout<<"Base DoSom/n";
}
};
class Derived : public Base
{
public:
Derived()
{
cout<<"Derived Init /n";
}
virtual ~Derived()
{
cout<<"Derived ~~/n";
}
void DoSome()
{
cout<<"Derived DoSome /n";
}
};
int main(int argc, char* argv[])
{
// Derived * d = new Base();这样写是错误的 因为基类不包含全部子类成员所以不能用基类初始化
Base * d = new Derived(); //这样写是对的 在new Derived的过程中调用了d的构造函数
while (1)
{}
}
程序输出如下:
Base Init
Derived Init
main函数修改一下
int main(int argc, char* argv[])
{
Base * d = new Derived(); //用子类初始化父类
d->DoSome(); //调用的是父类的函数
delete d;
while (1)
{}
}
程序输出如下:
Base Init 初始化子类
Derived Init 初始化父类
Base DoSom 调用父类函数
Derived ~~ 调用子类析构函数
Base ~~ 调用父类析构函数
现在我们把基类和子类该一下
把子类的析构函数的virtual去掉
class Base
{
public:
Base()
{
cout<<"Base Init/n";
}
~Base()
{
cout<<"Base ~~/n";
}
void DoSome()
{
cout<<"Base DoSom/n";
}
};
class Derived : public Base
{
public:
Derived()
{
cout<<"Derived Init /n";
}
~Derived()
{
cout<<"Derived ~~/n";
}
void DoSome()
{
cout<<"Derived DoSome /n";
}
};
int main(int argc, char* argv[])
{
Base * d = new Derived();
d->DoSome(); //调用的是基类的函数
delete d; //只调用基类的析构函数
while (1)
{}
}
输出如下:
Base Init
Derived Init
Base DoSom
Base ~~
再改一下程序:析构和DoSome函数都加上virtual
class Base
{
public:
Base()
{
cout<<"Base Init/n";
}
virtual ~Base()
{
cout<<"Base ~~/n";
}
virtual void DoSome()
{
cout<<"Base DoSom/n";
}
};
class Derived : public Base
{
public:
Derived()
{
cout<<"Derived Init /n";
}
~Derived()
{
cout<<"Derived ~~/n";
}
void DoSome()
{
cout<<"Derived DoSome /n";
}
};
int main(int argc, char* argv[])
{
Base * d = new Derived();
d->DoSome();
delete d;
while (1)
{}
}
程序输出如下
Base Init
Derived Init
Derived DoSome 子类的函数
Derived ~~
Base ~~
咱么现在来总结一下:
在基类用子类构造的前提下
若基类的DoSome是虚函数
则调用子类的DoSome函数
若基类的DoSome不是虚函数
则调用基类的DoSome函数
简单来说就是这么个规律,但是为什么呢,咱么来点有深度的
编译器在编译一个有虚函数的类时会为此类生成一个虚拟函数表vtable
表的值就是指向虚函数地址的指针
在调用类的构造函数时,指向基础类的指针此时已经变成指向具体的类的this指针,这样依靠此this指针即可得到正确的vtable,从而实现了多态性。在此时才能真正与函数体进行连接,这就是动态联编。