--------------"感谢在那每一次跌倒了以后,又重新来过"
(1)多态的概念以及定义:
①定义:
多态:俗称多种形态。每个具体的行为,去做同一件事情,产生不同的状态。
对语言来说,也就是灵活调用。
多态有两个种类;
1.静态的多态,也就是函数重载;(编译时,依靠函数名修饰规则)
2.动态的多态(运行时,找到父类、子类虚函数),构成条件如下......
(2)多态实现:
构成条件:
1. 必须通过基类的指针或者引用调用虚函数
2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
父类指针、引用指向父类对象 调用父类虚函数
父类指针、引用指向子类对象 调用子类虚函数 ----->指向哪个对象的调用哪个
这里就有个问题---->什么是虚函数?
(3)虚函数:
即被virtual修饰的函数(这和虚继承的关键字一样,但意义不一样!!!)
class Person
{
public:
//虚函数
virtual void PrintTicket()
{
cout << "买票---全价" << endl;
}
};
什么又叫做虚函数重写呢?
class Person
{
public:
virtual void PrintTicket()
{
cout << "买票---全价" << endl;
}
};
class Student:public Person
{
public:
virtual void PrintTicket()
{
cout << "买票---半价" << endl;
}
};
class Soilder:public Person
{
public:
virtual void PrintTicket()
{
cout << "买票---优先" << endl;
}
};
也就是,在派生类中有一个跟基类完全相同的虚函数。
他们在返回类型、函数名、参数列表 完全相同。
class Person
{
public:
virtual void PrintTicket()
{
cout << "买票---全价" << endl;
}
};
//虚函数重写
class Student :public Person
{
public:
virtual void PrintTicket()
{
cout << "买票---半价" << endl;
}
};
class Soilder :public Person
{
public:
virtual void PrintTicket()
{
cout << "买票---优先" << endl;
}
};
//父类指针\引用 调用
void Func(Person& p)
{
p.PrintTicket();
}
void Func(Person* p)
{
p->PrintTicket();
}
虚函数重写例外(例外 构成重写条件)
1.协变(基类和派生类 返回值可以不同)
我们来看看下面代码:
class A{};
class B :public A{};
class ForA
{
public:
virtual A* Print()
{
cout << "ForA()" << endl;
return new A;
}
};
class ForB:public ForA
{
public:
virtual B* Print()
{
cout << "ForB()" << endl;
return new B;
}
};
A是基类,B是子类。他们分别作为另外一组继承关系的返回值。 此时他们构成协变。
2.析构函数的重写:
class A
{
public:
~A()
{
cout << "~A()" << endl;
}
};
class B:public A
{
public:
~B()
{
cout << "~B()" << endl;
}
};
我们分别对A、B生成的对象进行析构
这和我们想要的不太一样。因为我们new 出来的B类并没有去调用析构 反而调用了两次A析构。
我们知道,编译器会把基类、派生类的析构函数统一改成,destructor(),从而隐藏,但在这里也就误打误撞构成 也就完成了重写。
class A
{
public:
//基类 带上虚函数 方便 子类重写
virtual ~A()
{
cout << "~A()" << endl;
}
};
class B:public A
{
public:
virtual ~B()
{
cout << "~B()" << endl;
}
};
从而,让虚函数进行重写了。a,b才能分别找到自己对应的 析构函数进行 清理!实现多态。
3.基类构成虚函数后,子类只需要重写
这个也算C++设计的一个坑。搞得重写不太严谨。
这样的理由在于,析构时,让父类构成虚函数(virtual)后,子类也就继承virtual的属性,让子类也对函数进行了重写。
class A
{
public:
//这只让 A 构成虚函数
virtual ~A()
{
cout << "~A()" << endl;
}
};
class B:public A
{
public:
//继承 虚函数的特性
~B()
{
cout << "~B()" << endl;
}
};
(4)C++11引入新关键字
final:修饰的虚函数不能被继承
class Car
{
public:
virtual void Drive() final{}
};
class BMW :public Car
{
public:
virtual void Drive();
};
2.override:检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错
class Car
{
public:
virtual void Drive() {}
};
class BMW :public Car
{
public:
virtual void Drive() override
{}
};
(5)概念对比与区别
学到现在,一定对有些概念记得混淆。重写、隐藏、重定义.......
多态上篇也就告一段落,感谢你的阅读。
祝你好运~