c++的多态
众所周知 c++ 类有多种形态 类之间出现多种结构的时候 就用到到多态了 c++ 多态意味着 调用成员函数时候 对象的类型 执行不同函数
c++
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Triangle class area :" <<'endl';
return (width * height / 2);
}
};
// 程序的主函数
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// 存储矩形的地址
shape = &rec;
// 调用矩形的求面积函数 area
shape->area();
// 存储三角形的地址
shape = &tri;
// 调用三角形的求面积函数 area
shape->area()
return 0;
}
输出错误的原因是 调用的函数版本是基类 由于编译的时候绑定 准备好了 这就是早绑定 area() 在调用的时候就准备好了
导致错误输出的原因是,调用函数 area() 被编译器设置为基类的版本,这就是所谓的静态多态,或静态链接 - 函数调用在程序执行前就准备好了
但是有关键字就不一样了 __ virtual __ 就不一样了设置 一下 (虚函数的声明)
c++
class Shape-{
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height =b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
// 基于runnoob
}
这是多态的使用方式, 这回看的是他的指针内容 不是直接看他的类型
虚函数
虚函数 是基类中使用 的关键字 vitual 的声明函数,定义这个函数的时候这个操作,不要求进行静态链接 要求的是任意点对象调用的类型都能用 这个操作叫动态链接 虚函数 虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。 我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。 或者说可以通过设置指针来选择访问 比如说
c++
Student s1(1,2,3) ; //传统派不用虚函数的方式
Teacher t2 (2,3,4);
*ptr = &s1 ;//绑定s1的地址
ptr->display(); //输出s1
*ptr =&t2 ;
ptr ->display(); //输出 t2
由于假设两个派生类都有display()那么 输出的那个只能是第一个 display()的 前面说了是因为是早绑定 第二个display 没有用到 所以要想两个类型的display都能用到 就只能 使用 virtual 的声明 声明为虚函数 如果 第一个display()声明了 例如 virtual void display() (备注这个是在类里面声明的) 这种的声明就可以调用第二个函数了
- 如果在 类里面定义了 virtual 类外定义就不用定义了 通过指针变量来访问就会自动调用 同名的虚函数
虚函数实用性
虚函数在某些方面的实用性
- 什么时候使用虚函数 , 和虚函数 注意事项
- 用vitual 声明的才叫虚函数 不能将类外的 成员声明哦 他的原理是允许对基类的虚函数进行重新定义 显而易见 他是在继承的层次中
c++
#include <iostream> // 举例
class Animal {
public:
virtual void speak() const {
std::cout << "The animal speaks" << std::endl;
}
virtual ~Animal() {} // 虚析构函数
};
class Dog : public Animal {
public:
void speak() const override {
std::cout << "The dog barks" << std::endl;
}
};
int main() {
Animal* myAnimal = new Dog();
myAnimal->speak(); // 输出 "The dog barks"
delete myAnimal;
return 0;
}
一定要在基类定义哦!!!!!!!!!!!!!!!
虚析构函数
之前我说过 析构函数是class 类结束清理内存
用new 执行的临时对象只会执行基类的 的时候不会执行派生类的析构函数 通过将基类的析构函数声明为虚函数,可以确保在删除派生类对象时,派生类的析构函数也会被调用,从而正确清理派生类中的资源。