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 对比
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号