C++多态,模板与泛型编程

0 引言

本文探讨一些C++的基本语法,包括C++多态(polymorphism),模板(template)与泛型编程(generic programming)。

(1)basic C++: 

https://www.learncpp.com/

(2)C++ 多态: 

https://www.runoob.com/cplusplus/cpp-polymorphism.html

https://zhuanlan.zhihu.com/p/37340242

(3)模板与泛型编程

https://www.programiz.com/cpp-programming/class-templates

1 C++多态


多态性可以简单概括为“一个接口, 多种方法”。 它是面向对象编程领域的核心问题。

C++ 支持两种多态: 

1. 编译时多态性(静态多态):通过重载函数实现:先期联编 early binding

(1) 函数重载(function overloading):通过重载使得函数具备不同的输入类型/输入变量个数,或者执行不同的操作。

(2) 运算符重载 (operator overloading):通过重载使得运算符在当前类对象的运算中具备独特的含义

(3) 函数覆盖(function overriding): 子类覆盖父类的实现

2. 运行时多态性(动态多态):通过虚函数实现 :滞后联编 late binding

#include <iostream> 
using namespace std;
 
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;
      }
};
class Rectangle: public Shape{
   public:
      Rectangle( int a=0, int b=0):Shape(a, b) { }
      virtual 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) { }
      virtual 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(); ///< before virtual: all call base->area();
///< after virtual: all call derived->area, which is polymorphism
return 0; }

 

2模板与泛型编程


 这里有一些最基本的例子可以帮助理解模板类和模板函数。

 

  

3 模板类的多态


 目前不支持将模板类中的template function设为virtual,     https://stackoverflow.com/questions/2354210/can-a-class-member-function-template-be-virtual

#include <iostream>

template <typename T>
class Geometry {
public:
    Geometry(const T& area) {
        d_area = area;
        std::cout << "construct Geometry object by area value!\n";
    }
    Geometry() {
        d_area = 0.0d;
        std::cout << "construct Geometry object by empty param!\n";
    }
    ~Geometry()  {
        std::cout << "deconstruct Geometry object!\n";
    }

    /* no virtual
    T getArea() {
        return d_area;
    }
    */
    template <typename T1>
    virtual T1 getArea() {
        return d_area;
    }

private:
    T d_area;
};

template <typename T>
class Triangle: public Geometry<T> {
public:
    Triangle(const T& area): Geometry<T>(area) {
        d_width = 0.0d;
        d_height = 0.0d;
        std::cout << "construct Triangle object by area value!\n";
    }
    Triangle(const T& width, const T& height): Geometry<T>(0.0d) {
        d_width = width;
        d_height = height;
        std::cout << "construct Triangle object by width and height value!\n";
    }
    ~Triangle() {
        std::cout << "deconstruct Triangle object by area value!\n";
    }

    /* no virtual
    T getArea() {
        d_area = 0.5d * d_width * d_height;
        return d_area;
    }
    */
    template <typename T1>
    virtual T1 getArea() {
        d_area = 0.5d * d_width * d_height;
        return d_area;
    }

private:
    T d_width;
    T d_height;
    T d_area;
};


int main()
{
    Geometry<double>* geom;
    Triangle<double> tri(7.0d, 8.0d);
    geom = &tri; 
    std::cout << "area of triangle = " << geom->getArea<double>() << std::endl;  ///< when no virtual function, geom will call 

    return 0;
}

compiling result:  template_virtual.cpp:24:5: error: templates may not be ‘virtual’

Solution for this usage;

#include <iostream>

template <typename T, typename T1>
class Geometry {
public:
    Geometry(const T& area) {
        d_area = area;
        std::cout << "construct Geometry object by area value!\n";
    }
    Geometry() {
        d_area = 0.0d;
        std::cout << "construct Geometry object by empty param!\n";
    }
    ~Geometry()  {
        std::cout << "deconstruct Geometry object!\n";
    }

    /* no virtual
    T getArea() {
        return d_area;
    }
    */
    virtual T1 getArea() {
        return d_area;
    }

private:
    T d_area;
};

template <typename T, typename T1>
class Triangle: public Geometry<T, T1> {
public:
    Triangle(const T& area): Geometry<T, T1>(area) {
        d_width = 0.0d;
        d_height = 0.0d;
        std::cout << "construct Triangle object by area value!\n";
    }
    Triangle(const T& width, const T& height): Geometry<T, T1>(0.0d) {
        d_width = width;
        d_height = height;
        std::cout << "construct Triangle object by width and height value!\n";
    }
    ~Triangle() {
        std::cout << "deconstruct Triangle object by area value!\n";
    }

    /* no virtual
    T getArea() {
        d_area = 0.5d * d_width * d_height;
        return d_area;
    }
    */
    virtual T1 getArea() {
        d_area = 0.5d * d_width * d_height;
        return d_area;
    }

private:
    T d_width;
    T d_height;
    T d_area;
};


int main()
{
    Geometry<double, double>* geom;
    Triangle<double, double> tri(7.0d, 8.0d);
    geom = &tri; 
    std::cout << "area of triangle = " << geom->getArea() << std::endl;  ///< when no virtual function, geom will call 

    return 0;
}

 it compiles good.

  

4 对比

 

posted @ 2020-10-01 21:35  十步一杀2017  阅读(218)  评论(0编辑  收藏  举报