C++多态
多态——面向对象编程三大特性之一
主要通过虚函数和纯虚函数实现多态。
多态种类
虚函数实现多态案例:
class BaseCalc
{
public:
virtual int GetIntResult(void) //虚函数
{
return 0;
}
virtual double GetFloatResult(void) //虚函数
{
return 0;
}
public:
int intNum1;
int intNum2;
double doubleNum1;
double doubleNum2;
};
class AddCalc : public BaseCalc
{
public :
int GetIntResult(void) //子类中重写父类中定义的虚函数
{
return (intNum1 + intNum2);
}
double GetFloatResult(void) //子类中重写父类中定义的虚函数
{
return (doubleNum1 + doubleNum2);
}
AddCalc(int num1, int num2)
{
intNum1 = num1;
intNum2 = num2;
}
AddCalc(double num1, double num2)
{
doubleNum1 = num1;
doubleNum2 = num2;
}
};
class SubCalc : public BaseCalc
{
public :
int GetIntResult(void)
{
return (intNum1 - intNum2);
}
double GetFloatResult(void)
{
return (doubleNum1 - doubleNum2);
}
SubCalc(int num1, int num2)
{
intNum1 = num1;
intNum2 = num2;
}
SubCalc(double num1, double num2)
{
doubleNum1 = num1;
doubleNum2 = num2;
}
};
class MulCalc : public BaseCalc
{
public :
int GetIntResult(void)
{
return (intNum1 * intNum2);
}
double GetFloatResult(void)
{
return (doubleNum1 * doubleNum2);
}
MulCalc(int num1, int num2)
{
intNum1 = num1;
intNum2 = num2;
}
MulCalc(double num1, double num2)
{
doubleNum1 = num1;
doubleNum2 = num2;
}
};
class DivCalc : public BaseCalc
{
public :
int GetIntResult(void)
{
if(intNum2 != 0)
{
return (intNum1 / intNum2);
}
else
{
cout << "除数不能为0" << endl;
}
}
double GetFloatResult(void)
{
if(doubleNum2 != 0)
{
return (doubleNum1 / doubleNum2);
}
else
{
cout << "除数不能为0" << endl;
}
}
DivCalc(int num1, int num2)
{
intNum1 = num1;
intNum2 = num2;
}
DivCalc(double num1, double num2)
{
doubleNum1 = num1;
doubleNum2 = num2;
}
};
int main()
{
AddCalc *addCalc = new AddCalc(2, 3);
cout << addCalc->intNum1 << "+" << addCalc->intNum2 << "=" << addCalc->GetIntResult() << endl;
delete addCalc;
return 0;
}
纯虚函数和抽象类
纯虚函数在父类中实现没有意义,其实现在子类中实现。
所以可以把虚函数定义为纯虚函数
纯虚函数语法:
virtual <返回值类型> <函数名> ( <参数列表> ) = 0;
抽象类
包含虚函数(虚函数和纯虚函数)的类,称为抽象类
- 无法实例化
- 子类必须重写抽象类中纯虚函数,否则子类也属于抽象类
虚析构和纯虚析构
虚析构和纯虚析构作用
虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象
——百度百科
解决方式:
将父类的析构函数定义为虚析构或纯虚析构
虚析构语法:
virtual ~<类名>()
{
}
例子:
- 虚析构函数
class Person
{
public:
int age;
public:
virtual ~Person() //虚析构函数
{
...
}
}
-
纯虚析构函数
包含纯虚析构函数的类也是抽象类,不能被实例化。
class Person { public: int age; public: virtual ~Person() = 0; //纯虚析构函数 } Person::~Person() //纯虚析构函数 { ... }
实例:
class Person
{
public:
Person()
{
cout << "Person构造函数" << endl;
}
virtual void Speak() = 0;
~Person()
{
cout << "Person析构函数" << endl;
}
};
class Student : public Person
{
public:
Student(string name, int age = 20)
{
cout << "Student构造函数调用" << endl;
m_Name = new string(name);
m_Age = age;
}
void Speak()
{
cout << *m_Name << "is Speaking" << endl;
}
~Student()
{
cout << "Student析构函数调用! " << endl;
if(this->m_Name != NULL)
{
delete m_Name;
m_Name = NULL;
}
}
public:
int m_Age;
string *m_Name;
};
void test()
{
Person *person = new Student("Tom");
person->Speak();
delete person;
}
int main(void)
{
test();
return 0;
}
从结果看Student的析构没有被调用,这样就会造成内存泄漏
解决:
//将父类的析构函数函数定义为虚析构函数or纯虚析构函数
class Person
{
public:
Person()
{
cout << "Person构造函数" << endl;
}
virtual void Speak() = 0;
virtual ~Person() //定义为虚析构函数
{
cout << "Person析构函数" << endl;
}
};
派生类的析构函数被调用,解决内存泄漏的问题。
注意:
- 某个类不包含虚函数,一般它不当做基类来使用。
- 不做基类的类,不要将析构函数定义为虚函数,这样会增加虚函数表,使对象的体积翻倍,以及可能降低其可移植性
- 抽象类是用来做基类的,必须有虚析构函数。