学习C++中的多态-创新互联
一、概念
创新互联服务项目包括桃山网站建设、桃山网站制作、桃山网页制作以及桃山网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,桃山网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到桃山省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!多态是面向对象程序设计的三大特征之一。封装性是基础,继承性是关键,多态性是补充,而多态又存在于继承的环境之中。多态性的含义就是多种状态。C++语言中支持两种多态性。一种是函数重载和运算符重载,又被称为静态多态,另一种是动态联编和虚函数,被称为动态多态。在这里主要讨论第一种和第二种的虚函数。
1.函数重载
函数重载简单的说就是给一个函数名多个含义。C++语言中允许在相同的作用域内以相同的名字定义几个不同实现的函数。定义这种重载函数时要求函数的参数或者至少有一个类型不同,或者个数不同,或者顺序不同。参数个数和类型,顺序都相同,仅返回值不同的重载函数是非法的。因为编译程序在选择相同名字的重载函数是仅考虑函数参数列表,即要根据函数参数列表中的参数个数、参数类型或参数顺序的差异进行选择。
举例:string类的构造函数重载(编译环境:VS2013)
#define _CRT_SECURE_NO_WARNINGS 1 #includeusing namespace std; #include class String { public: String(char *s) { length = strlen(s); ps = new char[length + 1]; strcpy(ps, s); } String(string &s) { length = s.length; ps = new char[length + 1]; strcpy(ps, s.ps); } String(int size = 20) { length = size; ps = new char[length + 1]; *ps = '\0'; } ~String() { delete ps; } int getlen() { return length; } void print() { cout << ps << endl; } private: char* ps; int length; }; int main() { String str1("String"); str1.print(); cout << str1.getlen() << endl; char *ps1 = "String Pionter"; String str2(ps1); String str3(str2); str3.print(); cout << str3.getlen() << endl; system("pause"); return 0; }
String类的构造函数被重载了三次,
str1("String")调用构造函数String(char *s);
str2(ps1)调用构造函数String(char *s);
str3(str2)调用构造函数String(String);
2.运算符重载
运算符重载重载就是赋予已有的运算符多重定义,使它具多种多种功能。
定义方法:类名 operator运算符(参数列表){ }
下面的运算符在C++中允许重载:
算数运算符: +, -, *, /, %, ++, --
位操作运算符: &,|, ~, ^, <<,>>
逻辑运算符: !, &&, ||
比较运算符: <, >, <=, >=, ==, !=
赋值运算符: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
其它运算符: [], (), ->, ', new, delete, new[], delete[]
下列运算符不允许重载:
·,·*, ::,?
使用运算符重载的注意:
用户重新定义运算符时,不改变原运算符的优先级和结合性。不改变运算符的操作数个数和语法结构,单目运算符只能重载为单目运算符,双目运算符只能重载双目运算符。
重载运算符不能有二义性。
运算符重载举例:
//运算符重载 #includeusing namespace std; class Complex { //friend Complex operator+(Complex c1, Complex c2); public: Complex(double real = 0.0, double p_w_picpath = 0.0) : _real(real) , _p_w_picpath(p_w_picpath) {} Complex(const Complex& c) : _real(c._real) , _p_w_picpath(c._p_w_picpath) {} Complex operator+(const Complex& c1) { return Complex(_real + c1._real, _p_w_picpath + c1._p_w_picpath); } Complex operator-(const Complex& c1) { return Complex(_real - c1._real, _p_w_picpath - c1._p_w_picpath); } Complex operator*(const Complex& c1) { return Complex(_real*c1._real - _p_w_picpath*c1._p_w_picpath, _real*c1._p_w_picpath + _p_w_picpath*c1._real); } Complex operator/(const Complex& c1) { return Complex((_real*c1._real + _p_w_picpath*c1._p_w_picpath) / (c1._p_w_picpath*c1._p_w_picpath + c1._real*c1._real), (_p_w_picpath*c1._real - _real*c1._p_w_picpath) / (c1._p_w_picpath*c1._p_w_picpath + c1._real*c1._real)); } Complex& operator+=(const Complex& c1) { _real = _real + c1._real; _p_w_picpath = _p_w_picpath + c1._p_w_picpath; return *this; } Complex& operator-=(const Complex& c1) { _real = _real - c1._real; _p_w_picpath = _p_w_picpath - c1._p_w_picpath; return *this; } Complex& operator*=(const Complex& c1) { double tmp = _real; _real = _real*c1._real - _p_w_picpath*c1._p_w_picpath; _p_w_picpath = tmp*c1._p_w_picpath + _p_w_picpath*c1._real; return *this; } Complex& operator/=(const Complex& c1) { double tmp = _real; _real = (_real*c1._real + _p_w_picpath*c1._p_w_picpath) / (c1._p_w_picpath*c1._p_w_picpath + c1._real*c1._real); _p_w_picpath = (_p_w_picpath*c1._real - tmp*c1._p_w_picpath) / (c1._p_w_picpath*c1._p_w_picpath + c1._real*c1._real); return *this; } // 只比较实部 bool operator<(const Complex& c) { if (_real (const Complex& c) { if (_real>c._real) { return true; } else { return false; } } bool operator<=(const Complex& c) { if ((_real 对复数的四则运算,++,--(前置,后置)等进行了重载。
3.虚函数
使用virtual关键字修饰函数时,指明该函数为虚函数,派生类需要重新实现,编译器将实现动态绑定。
总结:
1、派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外)
2、基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。
3、只有类的成员函数才能定义为虚函数,静态成员函数不能定义为虚函数。
4、如果在类外定义虚函数,只能在声明函数时加virtual关键字,定义时不用加。
5、构造函数不能定义为虚函数,虽然可以将operator=定义为虚函数,但最好不要这么做,使用时容易混淆
6、不要在构造函数和析构函数中调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会出现未定义的行为。
7、最好将基类的析构函数声明为虚函数。(析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但是构成覆盖,这里编译器做了特殊处理)
8、虚表是所有类对象实例共用的。
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
分享名称:学习C++中的多态-创新互联
当前链接:http://cdiso.cn/article/dciojd.html