多态——在我写这篇文章之前,我一直认为多态指的是“运行时多态”,就是在基类中借助virtual关键字实现的。
好,看到这里,忘记上面那句话。
1. 多态是如何实现绑定的
多态的绑定可以分为运行时多态和编译时多态。
编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数决定实现何种操作。(有些人写的是根据参数列表和返回值,但返回值在C++中式可以忽略的,因为其实返回值并不影响编译器的决定)
运行时多态是由虚函数实现的,是指直到系统运行时,才根据实际对象决定选择何种操作。
2.多态的实现
C++只要在基类中在函数前加上virtual关键字即可声明虚函数,子类中不需要virtual关键字,只要函数的返回类型与函数名称及参数列表与基类中一致,将自动成为虚函数。
#include<iostream>
using namespace std;
class A
{
public:
void foo()
{
printf("1\n");
}
virtual void fun()
{
printf("2\n");
}
};
class B : public A
{
public:
void foo()
{
printf("3\n");
}
void fun()
{
printf("4\n");
}
};
int main(void)
{
A a;
B b;
A *p = &a;
p->foo();
p->fun();
p = &b;
p->foo();
p->fun();
return 0;
}
注意p=&b时,A类指针p指向的是B类对象,你觉得他会输出什么?自己试试看就知道了
关于虚函数的问题我自己今天突发奇想说虚函数在子类中是不是跟函数重载一样不看返回类型?试了下以下代码:
#include <iostream>
using namespace std;
class ClxBase
{
public:
ClxBase() {};
virtual ~ClxBase() { cout << "Do something in class ClxBase!" << endl; };
virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
class ClxDerived : public ClxBase
{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
string DoSomething() { cout << "Do something in class ClxDerived!" << endl; return "Do something in class ClxDerived!";};
};
int main(){
ClxBase *pTest = new ClxDerived;
pTest->DoSomething();
delete pTest;
}
结果连编译都没通过……,codeblocks直接提示conflicting return type specified for `virtual std::string ClxDerived::DoSomething()'哎呀笨死了……子类虽然没有声明virtual但是它也继承了基类的DoSomething啊,我这不是重定义么……
多态的实现原理是什么?搞明白再回来写过