C++静态多态(模版模拟多态)的讨论
说到面向对象特性之一“多态”,以我的水平已经说不出太多新意了。相信很多程序员代码K多了,做梦都在“多态中”运行着。常规的多态是C++语义内置支持的一种特性,通过虚函数可以实现这个特性,为了后面以示区别,我们姑且把这种多态称为“动态多态”或”运行期多态“,而本文总主要想讨论下“静态多态”,也可以叫“编译期多态”,同时一起来看下,静态多态会给我们带来哪些惊喜之处,拭目以待吧。
- #include <iostream>
- #include <string>
- class BasicClassic
- {
- public:
- virtual void Print() = 0;
- };
- class DerivedClassic1 : public BasicClassic
- {
- public:
- DerivedClassic1() {}
- virtual void Print() {
- std::cout << "DerivedClassic1 Print" << std::endl;
- }
- };
- class DerivedClassic2 : public BasicClassic
- {
- public:
- DerivedClassic2() {}
- virtual void Print() {
- std::cout << "DerivedClassic2 Print" << std::endl;
- }
- };
- template<typename Derived>
- class Basic
- {
- public:
- inline void Print() {
- SelfCast()->Print();
- }
- protected:
- inline Derived* SelfCast() {
- return static_cast <Derived*>(this);
- }
- };
- class Derived1 : public Basic<Derived1>
- {
- public:
- Derived1() {}
- inline void Print() {
- std::cout << "Derived1 Print" << std::endl;
- }
- };
- class Derived2 : public Basic<Derived2>
- {
- public :
- Derived2() {}
- inline void Print() {
- std::cout << "Derived2 Print" << std::endl;
- }
- static std::string Name() {
- return "Derived2 Class" ;
- }
- };
- Basic<Derived1>* der1 = new Derived1();
- der1->Print();
- Basic<Derived2>* der2 = new Derived2();
- der2->Print();
- 动态多态的多态性是在运行期决定的,而静态多态是在编译期就决定的
- 动态多态的实现需要更多空间上的开销,每个对象会因为一个虚函数而增加4bytes,静态多态则没有这个问题
- 动态多态的实现需要更多的时间开销,虚函数的调用在时间上都会比普通函数多一次整形加法和一次指针间接引用,静态多态中的调用则跟普通函数的调用开销相同
- 动态多态(虚函数)是C++编译器内置支持的一种实现方式,而静态多态则会额外带来一些使用的复杂性
- 动态多态中虚函数不能通过内联来优化执行效率,而静态多态中则可以通过内联来进一步优化函数执行效率
- template <typename Derived>
- class Basic
- {
- public :
- Basic() { }
- inline void Print() {
- std::cout << Basic<Derived>::Name() << std::endl;
- SelfCast()->Print();
- }
- static std::string Name() {
- return Derived::Name();
- }
- protected :
- inline Derived* SelfCast() {
- return static_cast <Derived*>( this);
- }
- };
- class Derived1 : public Basic<Derived1>
- {
- public :
- Derived1() {}
- inline void Print() {
- std::cout << "Derived1 Print" << std::endl;
- }
- static std::string Name() {
- return "Derived1 Class" ;
- }
- };
c++的模板是个很强很暴力的东西,可以轻松地模拟多态。下面举个例子:
====================================================================
#include <iostream>
#include <string>
using namespace std;
class StarDecorator//注意:与多态不同,不需要有类阶层(简单说不需要继承啥接口)
{
public:
void printHead()
{
cout << "**********" << endl;
}
void printTail()
{
cout << "**********" << endl;
}
};
class AddDecorator
{
public:
void printHead()
{
cout << "++++++++++" << endl;
}
void printTail()
{
cout << "++++++++++" << endl;
}
};
template<class Decorator>
class Printer
{
public:
void print(const string& str)
{
decorator.printHead();
cout << str << endl;
decorator.printTail();
}
private:
Decorator decorator;
};
int main(int argc, char* argv[])
{
Printer<StarDecorator> p1;
p1.print("Hello,World!");
Printer<AddDecorator> p2;
p2.print("Hello,World!");
return 0;
}
========================================
是不是很像多态?更具体地说是设计模式中的Strategy模式。
这么做的好处:
1)比用多态时简单,不需要先构建Strategy对象再传入构造函数,故构造对象的代码简洁。
2)灵活机动,不需要类阶层,只要实现相关接口就可以召之即来。如果没有实现相关接口会有明显的编译错误提示。
这么做的缺点——和c++模板的缺点是一样的:
1)易读性比较不好,调试比较困难
2)模板只能定义在.h文件中,当工程大了之后,编译时间十分的变态。
结论:有些场合可以让代码较简洁,但应避免在比较底层的地方使用。
评论:
这是一个比较普遍的例子,实现通过传递不同的模板类型参数,实现对不同类的功能的调用,
这就需要一个调用公共接口。这个接口 可以用函数模板来充当,也可以用类模板来充当。
如果用类模板来充当,这个类模板可以是一个任意的类模板,也可以将类继承派生机制用起来,使用具体类的基类作为公共接口。
WTL中就是这么干的。比如窗口类的派生类,在向其基类模板中传递参数时,将自身类名传递给基类的模板参数,这样,就实现在基类这个公共调用接口中 实现对派生类的调用!!!
这种方式优雅地将 继承、派生机制 和模板机制有机结合起来。
C++静态多态(模版模拟多态)的讨论相关推荐
- c++中的多态---1(多态概念,静态联编和动态联编,多态原理解析,重载,重写,重定义的对比)
多态的基本概念 多态是面向对象设计语言数据抽象和继承之外的第三个基本特征 多态性(polymorphism)提供接口与具体实现之间的另一层隔膜,从而将"what"和"ho ...
- C++知识点 多态、静态多态、动态多态
多态 有了继承才有多态的概念,首先说一下继承. 继承的概念是派生类可以调用基类的成员.常举的例子,动物是基类,它拥有所有动物共有的一些特征和方法.它会衍生出猫的类,狗的类,派生出的类除了有动物公共的特 ...
- 编写Java程序,以继承和多态思想模拟饲养员喂养不同动物的不同行为
返回本章节 返回作业目录 需求说明: 以继承和多态思想模拟饲养员喂养不同动物的不同行为 动物园有饲养员和动物,其中动物有老虎.马.猴子.羊.狼等. 饲养员对不同的动物有不同的喂养行为. 实现思路: 以 ...
- C++多态——静态多态与动态多态
多态 : 顾名思义,多态就是多种形态,也就是对不同对象发送同一个消息,不同对象会做出不同的响应. 并且多态分为静态多态和动态多态. 静态多态就是在系统编译期间就可以确定程序执行到这里将要执行哪个函数, ...
- 用多态实现模拟电脑-硬盘-U盘-MP3读写数据的功能
namespace 电脑_移动硬盘_U盘_MP3 { class Program { static void Main(string[] args) { ...
- java静态多态实例,java多态
市面上对于多态往往有两种说法,一种是多态是通过方法的重载和方法的重写来实现多态,另外一种是父类型的引用指向子类型的对象或者接口类型的引用指向实现接口的类的实例. 其实两种说法都不全面,首先,要从字面上 ...
- java 多态_Java面向对象 —— 多态
前两天已经相继介绍了Java面向对象的三大特性之中的封装.继承,所以今天就介绍Java面向对象的三大特性的最后一项,多态~ 首先讲一下什么是多态,以及多态需要注意的细节 什么是多态:一个对象具备多种形 ...
- C++编译时多态和运行时多态
C++编译时多态和运行时多态 作者:melonstreet 出处:https://www.cnblogs.com/QG-whz/p/5132745.html 本文版权归作者和博客园共有,欢迎转载,但未 ...
- c++ 多态 运行时多态和编译时多态_C++学习笔记之多态
多态是面向对象三大特性之一 多态分为两类: 静态多态:函数重载 和 运算符重载 属于静态多态,复用函数名 动态多态:派生类 和 虚函数 实现运行时多态 静态多态和动态多态的区别: 静态多态的函数地址早 ...
最新文章
- 《Python程序设计》题库(2)
- CodeForces 567F DP Mausoleum
- 统计学习方法(第二版)-学习笔记
- python构造callable_Python callable内置函数原理解析
- 美国科技投资交易约4.1%来自中国 投资仍然很困难
- 充值,提现功能涉及的多线程、队列问题
- ofo生死局:拿什么续命?
- 回文数c语言 字符串,力扣 009 回文数 C语言
- STM32开发环境配置
- 资源下载类网站源码 第二版本分享
- 2013 年 2 月专访董明珠
- python考拉兹猜想_Python练习题 042:Project Euler 014:最长的考拉兹序列
- 自定义身份证输入键盘
- Unity3d开发MOBA游戏类《王者荣耀》记录(一)
- Android远程登录Telnet配置
- linux下删除oracle数据库实例
- 博图买什么样配置的笔记本_西门子PLC编程软件-博图软件用什么配置的电脑最好?...
- 决策树 (Decision Tree) 原理简述及相关算法(ID3,C4.5)
- USB设备,鼠标,键盘使用CH372,CH375,进行模拟的历程
- ffdshow 源代码分析 3: 位图覆盖滤镜(设置部分Settings)