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 对比