老师留了一个作业,就是对虚函数的使用,没有什么难度,但就是对虚函数的性质用来用去,搞得我一次又一次的查资料,可能这也是每个人必走的吧,所以我准备分享一下我认为学习c++虚函数里面需要注意的性质以及用法。

 

只有调用基类的指针引用调用虚函数时,才会发生动态绑定。

  1. Derived d;//Derived是派生类,Base是基类
  2. Base *ptr=&d;//积累指针指向派生类的对象
  3. Base &ref=d;//基类引用作为派生类的别名
  4. Base b=d;//调用Base的拷贝函数用d构造b

 

    1. ptr->函数名,调用派生类中的对应函数
    2. ref.函数名,掉用派生类中的对应函数
    3. b.函数名,调用基础类中的对应函数

      

  1.  

 

  • 通过派生类对象访问同名函数。这是静态连编

  • 通过基类对象的指针访问同名函数。这也是静态连编

  • 通过基类对象的指针或引用访问同名虚函数,这是动态连编(老师喜欢考的)

    1. class P{public:f(){.....}};//father
    2. class C:public P{public:f(){....}};//son
    3. main(){
    4. P* ptr;
    5. P p;
    6. C c;
    7. ptr=&p;
    8. ptr->f();//调用P::f()
    9. ptr=&c;
    10. ptr->f();//调用P::f()
    11. }

      

  1.  

注意:要是没有vitural,指针什么类型就调用什么类型

 

 

  1. class A {
  2. public:
  3. virtual void foo() {}
  4. void bar() {}
  5. };
  6. class B : public A {
  7. public:
  8. void foo() const override { // 错误: B::foo 不覆写 A::foo
  9. } // (签名不匹配)
  10. void foo() override; // OK : B::foo 覆写 A::foo
  11. void bar() override {} // 错误: A::bar 非虚
  12. };
  13. void B::foo() override {// 错误: override只能放到类内使用
  14. }

  

  1.  

 

    1. class Animal
    2. {
    3. public:
    4. Animal();
    5. ~Animal();
    6. virtual Animal& speak() {//可以只在父类中定义vitural
    7. return *this;//注意一定要在每一个覆写的后面加上这个返回
    8. }
    9.  
    10. };
    11.  
    12. class Dog:public Animal
    13. {
    14. public:
    15. Dog();
    16. ~Dog();
    17. Dog& speak() {
    18. cout << "wang" << endl;
    19. delete this;
    20. return *this;
    21. }
    22. };
    23. void test(Animal& p){//注意:覆写之后暂时还没有效果,必须要定义一个void函数来调用,当然是用下面的方式来调用啦
    24. p.speak();
    25. }

      

  1.  

 

  1.  

 

  1. struct Base {
  2. virtual void foo();
  3. };
  4. struct A : Base
  5. {
  6. void foo() final; // A::foo 被覆写且是最终覆写
  7. void bar() final; // 错误:非虚函数不能被覆写或是 final
  8. };
  9. struct B final : A // struct B 为 final,不能被继承
  10. {
  11. void foo() override; // 错误: foo 不能被覆写,因为它在 A 中是 final
  12. };

  

 

 

特征:

  • 抽象类不能实例化。

  • 抽象类可以包含抽象方法和抽象访问器。

  • 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实际实现。

  • 必须是派生类来实现,而不是让基类实现

 

 

使用情况:下面会提到上转和下转,与其类似

  1.  

 

  1. // A function for displaying a Shape object
  2. void printObject(Shape &shape)
  3. {
  4. cout << "The area is "
  5. << shape.getArea() << endl;
  6. //这里就是判断是不是该类型是不是要转换的类型,当然必须用到指针
  7. Shape *p = &shape;
  8. Circle *c = dynamic_cast<Circle*>(p);
  9. // Circle& c = dynamic_cast<Circle&>(shape);
  10. // 引用转换失败则抛出一个异常 std::bad_cast
  11. if (c != nullptr) // 转换失败则指针为空
  12. {
  13. cout << "The radius is "
  14. << p1->getRadius() << endl;
  15. cout << "The diameter is "
  16. << p1->getDiameter() << endl;
  17. }
  18. }

  

 

  • 上转:upcasting : Assigning a pointer of a derived class type to a pointer of its base class type (将派生类类型指针赋值给基类类型指针)

    1. Shape* s = nullptr;
    2. Circle *c = new Circle(2);
    3. s = c; //OK,隐式上转

      

  1.  
  • 下转:downcasting : Assigning a pointer of a base class type to a pointer of its derived class type. (将基类类型指针赋值给派生类类型指针)

  1. Shape* s = new Circle(1);
  2. Circle *c = nullptr;
  3. c = dynamic_cast <Circle*> (s); //显式下转

 

好了,上面就是我对c++虚函数一些性质的简单总结和用法

版权声明:本文为instead-everyone原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/instead-everyone/p/12740911.html