多态:多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。--百度百科
C++中,实现多态有以下方法:虚函数,抽象类,覆盖,模板(重载和多态无关)。
多态的作用:
1. 应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。大大提高程序的可复用性。//继承
2. 派生类的功能可以被基类的方法或引用变量所调用,这叫向后兼容,可以提高可扩充性和可维护性。 //多态的真正作用
3.多态除了代码的复用性外,还可以解决项目中紧偶合的问题,提高程序的可扩展性.。耦合度讲的是模块模块之间,代码代码之间的关联度,通过对系统的分析把他分解成一个一个子模块,子模块提供稳定的接口,达到降低系统耦合度的的目的,模块模块之间尽量使用模块接口访问,而不是随意引用其他模块的成员变量
析构函数问题:
1.派生类指针指向派生类对象
析构函数不定义为虚函数和定义为虚函数结果相同,都能正常调用子类和父类的析构函数
class Base
{
public:
Base()
{
cout << "Base()" << endl;
}
~Base()
{
cout << "~Base()" << endl;
}
};
class Driver :public Base
{
public:
Driver()
{
cout << "Driver()" << endl;
}
~Driver()
{
cout << "~Driver()" << endl;
}
};
int main()
{
Driver *pd = new Driver;
delete pd;
system("pause");
return 0;
}
2.基类指针指向派生类对象
a.定义virtual
class Base
{
public:
Base()
{
cout << "Base()" << endl;
}
virtual ~Base()
{
cout << "~Base()" << endl;
}
};
class Driver :public Base
{
public:
Driver()
{
cout << "Driver()" << endl;
}
~Driver()
{
cout << "~Driver()" << endl;
}
};
int main()
{
Base *pd = new Driver;
delete pd;
system("pause");
return 0;
}
b.未定义virtual
结果只调用父类的析构函数,而没有调用子类的析构函数。
普通函数问题:
a.父类函数未定义为虚函数:
class Base
{
public:
void show() { cout << "BBB" << endl; }
~Base()
{
cout << "~Base()" << endl;
}
};
class Driver :public Base
{
public:
void show() { cout << "DDDr" << endl; }
~Driver()
{
cout << "~Driver()" << endl;
}
};
int main()
{
Base *pd1 = new Driver;
pd1->show();
delete pd1;
system("pause");
return 0;
}
会发现结果都是调用的父类的函数而不是子类的。
b.父类定义虚函数
class Base
{
public:
virtual void show() { cout << "BBB" << endl; }
virtual ~Base()
{
cout << "~Base()" << endl;
}
};
class Driver :public Base
{
public:
void show() { cout << "DDDr" << endl; }
~Driver()
{
cout << "~Driver()" << endl;
}
};
int main()
{
Base *pd1 = new Driver;
pd1->show();
delete pd1;
system("pause");
return 0;
}
结果调用的是子类的函数,且析构函数也调用了子类的析构函数。
总结:从上面可以看出多态如何起作用的,我们通过将子类赋值给父类进行初始化,实现了多态,即同一个父类接口,实现了复用,实现了不同的功能。但是为什么会出现调用问题?
《Effective C++》条款36 绝不重新定义继承而来的non-virtual函数
非虚函数重写,pd1是静态绑定的,其调用的non-virtual函数永远是Base所定义的版本,即使指向派生类的对象。
另一方面,virtual函数却是动态绑定的,所以无论子类还是父类调用show,都会进行动态绑定,绑定的是指向的类的函数。