萧山做网站的公司,个人发布信息免费推广平台,设计好的网站,华亭县门户网站目录
一、多态的定义
二、重载、覆盖(重写)、隐藏(重定义)的对比
三、析构函数重写
四、C11 override 和 final
1. final
2. override
五、抽象类
六、多态的原理 一、多态的定义
多态是在不同继承关系的类对象#xff0c;去调用同一函数#xff0c;产生了不同的行为…目录
一、多态的定义
二、重载、覆盖(重写)、隐藏(重定义)的对比
三、析构函数重写
四、C11 override 和 final
1. final
2. override
五、抽象类
六、多态的原理 一、多态的定义
多态是在不同继承关系的类对象去调用同一函数产生了不同的行为。比如Student继承了 Person。Person对象买票全价Student对象买票半价。
class Person {
public:virtual void BuyTicket() { cout 买票-全价 endl; }
};class Student : public Person {
public:virtual void BuyTicket() { cout 买票-半价 endl; }
};int main()
{Person Mike;Mike.BuyTicket();Student Johnson;Johnson.BuyTicket();return 0;
} 那么在继承中要构成多态还有两个条件 必须通过基类的指针或者引用调用虚函数被调用的函数必须是虚函数且派生类必须对基类的虚函数进行重写 二、重载、覆盖(重写)、隐藏(重定义)的对比 三、析构函数重写
如果基类的析构函数为虚函数此时派生类析构函数只要定义无论是否加virtual关键字 都与基类的析构函数构成重写虽然基类与派生类析构函数名字不同。虽然函数名不相同 看起来违背了重写的规则其实不然这里可以理解为编译器对析构函数的名称做了特殊处 理编译后析构函数的名称统一处理成destructor。
class Person {
public:virtual ~Person() { cout ~Person() endl; }
};class Student : public Person {
public:virtual ~Student() { cout ~Student() endl; }
};// 只有派生类Student的析构函数重写了Person的析构函数下面的delete对象调用析构函数才能构成多态才能保证p1和p2指向的对象正确的调用析构函数。
int main()
{Person* p1 new Person;Person* p2 new Student;delete p1;delete p2;return 0;
} 四、C11 override 和 final
C对函数重写的要求比较严格但是有些情况下由于疏忽可能会导致函数 名字母次序写反而无法构成重载而这种错误在编译期间是不会报出的只有在程序运行时没有 得到预期结果才来debug会得不偿失因此C11提供了override和final两个关键字可以帮 助用户检测是否重写。
1. final
修饰虚函数表示该虚函数不能再被重写
class Car
{
public:virtual void Drive() final {}
};
class Benz :public Car
{
public:virtual void Drive() { cout Benz-舒适 endl; }
};
2. override
检查派生类虚函数是否重写了基类某个虚函数如果没有重写编译报错。
class Car {
public:virtual void Drive() {}
};
class Benz :public Car {
public:virtual void Drive() override { cout Benz-舒适 endl; }
}; 五、抽象类
在虚函数的后面写上 0 则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类也叫接口 类抽象类不能实例化出对象。派生类继承后也不能实例化出对象只有重写纯虚函数派生 类才能实例化出对象。纯虚函数规范了派生类必须重写另外纯虚函数更体现出了接口继承。
class Car
{
public:virtual void Drive() 0;
};
class Benz :public Car
{
public:virtual void Drive(){cout Benz-舒适 endl;}
};
class BMW :public Car
{
public:virtual void Drive(){cout BMW-操控 endl;}
};
void Test()
{Car* pBenz new Benz;pBenz-Drive();Car* pBMW new BMW;pBMW-Drive();
} 接口继承与实现继承 普通函数的继承是一种实现继承派生类继承了基类函数可以使用函数继承的是函数的实 现。虚函数的继承是一种接口继承派生类继承的是基类虚函数的接口目的是为了重写达成 多态继承的是接口。所以如果不实现多态不要把函数定义成虚函数。 六、多态的原理
多态的关键在于通过基类指针或引用调用一个虚函数时编译时不能确定到底调用的是基类还是派生类的函数运行时才能确定。
class A
{
public:int i;virtual void Print() { } // 虚函数
};class B
{
public:int n;void Print() { }
};int main()
{cout sizeof(A) , sizeof(B);return 0;
}
在32位环境下运行上面函数。
可以发现有虚函数的类多出了4个字节在32位机子上指针类型大小正好是4个字节多出来这四个字节就是一个指向虚函数表的指针。
// 基类
class Base
{
public:int i;virtual void Print() { } // 虚函数
};// 派生类
class Derived : public Base
{
public:int n;virtual void Print() { } // 虚函数
};
上面 Derived 类继承了 Base类两个类都有「虚函数」那么它「虚函数表」的形式可以理解成下图