C++多态——虚函数virtual入门
首先要知道C++多态是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(或称为重写)。
虚函数虚就虚在在所谓“推迟联编”或者“动态联编”上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被成为“虚”函数。
虚函数的定义是在基类中进行的,它是在基类中需要定义为虚函数的成员函数的声明中冠以关键字virtual,从而提供一种接口界面。
另外,虚函数只能借助于指针或者引用来达到多态的效果。
这样说肯定不懂是吧,来看几个例子(输出结果自己测试):
class A {
public:
virtual void foo() { // 定义虚函数
cout << "A::foo() is called" << endl;
}
};
class B : public A {
public:
void foo() {
cout << "B::foo() is called" << endl;
}
};
int main(void) {
A *a = new B();
a->foo(); // 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!
return 0;
}
再来看一个例子:
class A {
public:
void foo() {
cout << "A::foo()" << endl;
}
virtual void fun() {
cout << "A::fun()" << endl;
}
};
class B : public A {
public:
void foo() { // 隐藏:派生类的函数屏蔽了与其同名的基类函数
cout << "B::foo()" << endl;
}
void fun() { // 多态、覆盖
cout << "B::fun()" << endl;
}
};
int main(void) {
A a;
B b;
A *p = &a;
p->foo(); // 输出A::foo()
p->fun(); // 输出A::fun()
p = &b;
p->foo(); // 取决于指针类型,输出A::foo()
p->fun(); // 取决于对象类型,输出B::fun(),体现了多态
return 0;
}
再来看个复杂点的例子:
class Family {
public:
Family(string name = "鲜花") : flower(name) { }
string getName() {
return flower;
}
virtual void like() {
cout << "家人喜欢不同的花:" << endl;
}
private:
string flower;
};
class Mother : public Family {
public:
Mother(string name = "月季") : Family(name) { }
void like() {
cout << "妈妈喜欢" << getName() << endl;
}
};
class Daughter : public Family {
public:
Daughter(string name = "百合") : Family(name) { }
void like() {
cout << "女儿喜欢" << getName() << endl;
}
};
int main() {
Family* p;
Family f;
Mother mom;
Daughter dau;
p = &f;
p->like();
p = &mom;
p->like();
p = &dau;
p->like();
return 0;
}