制作网站联系方式,吃什么补肾快,子域名查询ip,公司开发个网站多少钱文章目录 0. 引言1. 模板编程替换虚函数和多态的必要性1.1. MISRA C对类型转换和虚函数的规定1.2. 虚函数与多态问题的影响及如何适应MISRA C要求1.3. 模板编程的优势#xff1a;替代虚函数和多态机制 2. 设计模式改进2.1. 单例模式的改进与静态局部变量的对比(第二种实现) 2.… 文章目录 0. 引言1. 模板编程替换虚函数和多态的必要性1.1. MISRA C对类型转换和虚函数的规定1.2. 虚函数与多态问题的影响及如何适应MISRA C要求1.3. 模板编程的优势替代虚函数和多态机制 2. 设计模式改进2.1. 单例模式的改进与静态局部变量的对比(第二种实现) 2.2. 工厂模式的改进2.3. 观察者模式的改进2.4. 适配器模式的改进2.5. 桥接模式的改进2.6. 装饰器模式的改进2.7. 责任链模式的改进 0. 引言
MISRA C 标准对类型转换和虚函数使用做出严格规定尤其在嵌入式系统中以确保代码的可预测性和高效性。传统设计模式中虚函数和多态性引入会增加运行时开销增加系统负担。然而模板编程通过编译时决策代替运行时动态绑定可以提升性能并降低内存消耗。 本文将尝试使用C11改进常用的几个设计模式。
1. 模板编程替换虚函数和多态的必要性
1.1. MISRA C对类型转换和虚函数的规定
MISRA C 标准对于类型转换和虚函数的有严格的使用要求要求包括
Rule 5-0-1MISRA C 2008禁止使用不安全的类型转换如 reinterpret_cast、const_cast、static_cast 和 dynamic_cast。Rule 5-0-2要求类型转换必须明确指定转换类型确保转换符合预期行为避免使用不安全的转换方式。Rule 5-1-1在进行类型转换时必须确保转换类型合法不破坏对象的常量性或类型。
同时虚函数和多态机制在嵌入式系统中也有劣势
运行时开销虚函数表vtable的查找会带来额外的运行时开销增加程序的资源需求。RTTI运行时类型信息开销启用 RTTI 会增加内存使用尤其是在 dynamic_cast 或 typeid 被使用时。MISRA C的限制标准要求避免使用虚函数和多态机制特别是在没有严格控制的情况下可能会导致代码行为不可预测增加出错的风险。
1.2. 虚函数与多态问题的影响及如何适应MISRA C要求
虚函数和多态机制在嵌入式系统中往往面临以下问题
运行时性能问题虚函数表查找、RTTI机制的引入都会增加程序的运行时开销尤其是在资源受限的嵌入式系统中可能会显著影响系统性能。内存开销启用 RTTI 会使每个多态类占用额外的内存这对于内存有限的嵌入式系统是一个不小的负担。MISRA C的限制虚函数和多态机制的使用在 MISRA C 中受到限制因为它们增加了代码的复杂性降低了可预测性并且可能违反一些规则如避免不安全的类型转换。
为了适应 MISRA C 的要求可以考虑以下几点
避免虚函数和多态尽量避免使用运行时多态和虚函数减少 RTTI 开销避免使用 dynamic_cast 和 typeid。设计时决策通过明确的类型接口和结构体来实现类型转换确保每个类型转换都能被清晰审查和验证。使用强类型系统避免使用 void* 等不明确类型的指针确保类型清晰从而减少不必要的类型转换。
1.3. 模板编程的优势替代虚函数和多态机制
模板编程通过在编译时绑定函数和类避免运行时的虚函数查找和多态性问题。使用模板编程的优势如下
编译时绑定模板代码在编译时就确定了函数调用和对象行为避免了虚函数表的查找。内联优化编译器能够对模板代码进行内联优化直接将模板代码嵌入到调用点。提高执行效率由于没有动态绑定和运行时类型信息模板编程能够显著降低程序的运行时开销提升性能。
模板编程避免了虚函数和多态机制的开销并且在遵循 MISRA C 标准时能够更容易地实现高效且符合规范的设计模式。
2. 设计模式改进
在传统的设计模式中许多模式如单例模式、工厂模式、观察者模式等依赖于虚函数和继承来实现多态和灵活的行为切换。然而这种方式虽然灵活但会带来运行时的开销包括虚函数表查找、内存使用的增加以及与运行时类型信息RTTI相关的性能损失。
模板编程 和 静态多态 通过在编译时进行决策避免了虚函数调用和动态绑定的需要。通过使用模板我们可以在不牺牲灵活性的情况下提高代码的执行效率并且能够使代码更加符合 MISRA C 等标准的要求。
以下是一些常见设计模式的改进方式尽量在不违背设计原则的情况下提升代码的性能。
2.1. 单例模式的改进
传统的单例模式通过 static 变量和线程同步机制来保证只创建一个实例。然而如果使用虚函数或者多态在某些情况下可能会影响线程安全性增加程序的复杂度。在 C11/14 中可以利用 std::once_flag 和 std::call_once 来实现线程安全的单例而无需依赖虚函数。
通过模板和 std::unique_ptr 来管理单例实例可以避免虚函数的使用同时保证线程安全和内存管理。
#include iostream
#include memory // for std::unique_ptr
#include mutexclass Singleton {public:// 获取唯一实例static Singleton getInstance() {std::call_once(initFlag_, Singleton::initSingleton);return *instance_;}// 示例方法void doSomething() {std::cout Singleton instance is doing something! std::endl;}private:Singleton() {std::cout Singleton initialized! std::endl;}// 禁止拷贝构造和赋值操作Singleton(const Singleton) delete;Singleton operator(const Singleton) delete;// 使用 std::unique_ptr 管理单例实例static std::unique_ptrSingleton instance_;static std::once_flag initFlag_;// 初始化实例的私有方法static void initSingleton() {instance_ std::make_uniqueSingleton();}
};// 初始化静态成员
std::unique_ptrSingleton Singleton::instance_ nullptr;
std::once_flag Singleton::initFlag_;int main() {// 获取并使用单例对象Singleton singleton1 Singleton::getInstance();singleton1.doSomething();// 再次获取单例对象确保不会重新初始化Singleton singleton2 Singleton::getInstance();singleton2.doSomething();return 0;
}执行结果
Singleton initialized!
Singleton instance is doing something!
Singleton instance is doing something!与静态局部变量的对比(第二种实现)
请看如下的实现实现
class Singleton {public:static Singleton getInstance() {static Singleton instance;return instance;}private:Singleton() default;
};区别对比
特性第一种实现第二种实现线程安全性手动使用 std::once_flag 实现静态局部变量自动线程安全复杂性较高需维护多个静态成员和初始化方法较低逻辑直接嵌入函数内灵活性更灵活适合复杂初始化逻辑不够灵活构造函数绑定初始化逻辑析构时机使用 std::unique_ptr支持析构依赖静态变量销毁时机不可控适用场景更适合需要复杂初始化逻辑的场景适合大多数简单单例模式需求
2.2. 工厂模式的改进
工厂模式通常通过继承和虚函数来实例化不同的产品对象。而在使用模板的工厂模式中我们通过将产品类型作为模板参数来实现静态多态从而避免了使用虚函数。这种方式通过编译时的类型推导确保了工厂方法能够在编译时确定而不依赖于运行时的动态绑定。
CRTPCuriously Recurring Template Pattern是一种常见的技巧它通过将子类作为模板参数允许在基类中静态地定义行为从而避免了虚函数的开销。通过这样的改进我们可以在不牺牲灵活性的前提下减少运行时的性能损耗。
#include iostream
#include memory
#include type_traits// 基础产品接口
template typename ProductType
class Product {public:void operation() const {static_assert(std::is_base_ofProduct, ProductType::value, ProductType must be derived from Product);static_castconst ProductType*(this)-operationImpl();}private:// 使用 CRTP (Curiously Recurring Template Pattern) 进行静态多态void operationImpl() const delete;
};// 具体产品A
class ConcreteProductA : public ProductConcreteProductA {public:void operationImpl() const {std::cout ConcreteProductA operation. std::endl;}
};// 具体产品B
class ConcreteProductB : public ProductConcreteProductB {public:void operationImpl() const {std::cout ConcreteProductB operation. std::endl;}
};// 工厂类模板
template typename ProductType
class Factory {public:std::unique_ptrProductProductType create() const {return std::make_uniqueProductType();}
};int main() {FactoryConcreteProductA factoryA;auto productA factoryA.create();productA-operation();FactoryConcreteProductB factoryB;auto productB factoryB.create();productB-operation();return 0;
}执行结果
ConcreteProductA operation.
ConcreteProductB operation.2.3. 观察者模式的改进
在传统的观察者模式中观察者通常通过继承和虚函数来注册和通知其他对象。而在模板化的观察者模式中我们使用 std::function 来替代虚函数利用模板和类型擦除来实现更加高效和灵活的观察者模式。这样我们避免了虚函数的调用和继承结构的复杂性同时提高了类型安全性和灵活性。
#include functional
#include iostream
#include map
#include string
#include vectortemplate typename EventHandler
class Events {public:Events() : nextKey_(0) {}// 注册事件处理函数uint32_t addObserver(EventHandler handler) {uint32_t key nextKey_;storeHandler(key, std::forwardEventHandler(handler));return key;}uint32_t addObserver(EventHandler handler) {uint32_t key nextKey_;storeHandler(key, handler);return key;}// 移除事件处理函数void removeObserver(uint32_t key) {handlers_.erase(key);}// 通知所有注册的事件处理函数template typename... Argsvoid notifyAll(Args... args) {for (auto it : handlers_) {for (auto handler : it.second) {handler(std::forwardArgs(args)...);}}}// 触发事件通知所有注册的事件处理器template typename... Argsinline void trigger(Args... args) {notifyAll(std::forwardArgs(args)...);}// 删除拷贝构造和赋值操作Events(const Events) delete;Events operator(const Events) delete;~Events() default;// 通过 操作符添加事件处理器uint32_t operator(EventHandler handler) {return addObserver(std::forwardEventHandler(handler));}uint32_t operator(EventHandler handler) {return addObserver(handler);}// 通过 - 操作符移除事件处理器Events operator-(uint32_t key) {removeObserver(key);return *this;}// 清除所有事件处理器void clear() {handlers_.clear();}private:// 存储事件处理函数template typename Handlervoid storeHandler(uint32_t key, Handler handler) {handlers_[key].emplace_back(std::forwardHandler(handler));}private:uint32_t nextKey_; // 唯一的事件处理函数键值std::mapuint32_t, std::vectorEventHandler handlers_; // 存储事件处理函数支持多个处理器
};//
// 事件处理函数1
void handler1(int data) {std::cout Handler1 received data: data std::endl;
}// 事件处理函数2
void handler2(int data) {std::cout Handler2 received data: data std::endl;
}int main() {// 使用 int 作为事件的键类型事件处理函数是 std::functionvoid(int)Eventsstd::functionvoid(int) events;// 注册两个事件处理器到同一个事件auto eventKey1 events handler1;auto eventKey2 events handler2;// 触发事件所有绑定到该事件的处理器都会被调用events.trigger(100); // 输出// Handler1 received data: 100// Handler2 received data: 100// 移除事件处理器events - eventKey1;std::cout After removing handler1: std::endl;// 再次触发事件只有 handler2 会被调用events.trigger(200); // 输出Handler2 received data: 200return 0;
}执行结果:
Handler1 received data: 100
Handler2 received data: 100
After removing handler1:
Handler2 received data: 2002.4. 适配器模式的改进
适配器模式用于解决接口不兼容的问题。假设我们有一个基于激光雷达的数据接口但我们需要将这个接口适配到自动驾驶控制系统。
#include iostream
#include memoryclass RadarSensor {public:void readData() {std::cout Reading data from Radar Sensor.\n;}
};class CameraSensor {public:void captureImage() {std::cout Capturing image from Camera Sensor.\n;}
};// 适配器模板类
template typename T
class SensorAdapter {public:void operate() {static_assert(std::is_base_ofSensorAdapter, T::value, T must be derived from SensorAdapter);static_castT*(this)-operateImpl();}
private:void operateImpl() delete;
};class RadarAdapter : public SensorAdapterRadarAdapter {private:RadarSensor radar_;public:void operateImpl() {radar_.readData();}
};class CameraAdapter : public SensorAdapterCameraAdapter {private:CameraSensor camera_;public:void operateImpl() {camera_.captureImage();}
};int main() {RadarAdapter radarAdapter;CameraAdapter cameraAdapter;radarAdapter.operate(); // Reading data from Radar SensorcameraAdapter.operate(); // Capturing image from Camera Sensorreturn 0;
}执行结果
Reading data from Radar Sensor.
Capturing image from Camera Sensor.2.5. 桥接模式的改进
在桥接模式中模板类可以在编译时根据实现的类型来选择适当的操作从而避免了虚函数的调用开销。
#include iostream
#include memory// 实现接口通过模板类实现
template typename T
class Implementor {public:void operationImpl() const {static_assert(std::is_base_ofImplementor, T::value, T must be derived from Implementor);static_castconst T*(this)-operationImpl();}
};// 具体实现A
class ConcreteImplementorA : public ImplementorConcreteImplementorA {public:void operationImpl() const {std::cout ConcreteImplementorA operation. std::endl;}
};// 具体实现B
class ConcreteImplementorB : public ImplementorConcreteImplementorB {public:void operationImpl() const {std::cout ConcreteImplementorB operation. std::endl;}
};// 抽象类模板方法和组合
template typename T
class Abstraction {public:explicit Abstraction(std::shared_ptrImplementorT implementor) : implementor_(implementor) {}void operation() const {implementor_-operationImpl(); // 调用实现类的操作}protected:std::shared_ptrImplementorT implementor_;
};// 扩展抽象类A
template typename T
class RefinedAbstractionA : public AbstractionT {public:explicit RefinedAbstractionA(std::shared_ptrImplementorT implementor) : AbstractionT(implementor) {}void operation() const {std::cout RefinedAbstractionA operation: ;AbstractionT::operation();}
};// 扩展抽象类B
template typename T
class RefinedAbstractionB : public AbstractionT {public:explicit RefinedAbstractionB(std::shared_ptrImplementorT implementor) : AbstractionT(implementor) {}void operation() const {std::cout RefinedAbstractionB operation: ;AbstractionT::operation();}
};// 使用模板的桥接模式
int main() {// 创建具体实现auto implementorA std::make_sharedConcreteImplementorA();auto implementorB std::make_sharedConcreteImplementorB();// 创建抽象类A和BRefinedAbstractionAConcreteImplementorA abstractionA(implementorA);RefinedAbstractionBConcreteImplementorB abstractionB(implementorB);// 调用操作abstractionA.operation(); // 输出: RefinedAbstractionA operation: ConcreteImplementorA operation.abstractionB.operation(); // 输出: RefinedAbstractionB operation: ConcreteImplementorB operation.return 0;
}执行结果
RefinedAbstractionA operation: ConcreteImplementorA operation.
RefinedAbstractionB operation: ConcreteImplementorB operation.2.6. 装饰器模式的改进
装饰器模式通过动态地组合不同的功能来扩展对象的行为。传统的装饰器模式依赖于继承和虚函数来实现动态行为的扩展而模板化的装饰器模式通过组合和模板参数来实现类似的功能避免了虚函数的调用和继承层次的复杂性。
#include iostream
#include memory// 基本组件接口
template typename T
class Component {public:virtual void operation() 0;virtual ~Component() default;
};// 具体组件
class ConcreteComponent : public ComponentConcreteComponent {public:void operation() override {std::cout ConcreteComponent operation\n;}
};// 装饰器基类
template typename T
class Decorator : public ComponentT {protected:std::unique_ptrComponentT component_; // 装饰的组件public:explicit Decorator(std::unique_ptrComponentT component) : component_(std::move(component)) {}void operation() override {component_-operation();}
};// 具体装饰器A
class ConcreteDecoratorA : public DecoratorConcreteComponent {public:explicit ConcreteDecoratorA(std::unique_ptrComponentConcreteComponent component): DecoratorConcreteComponent(std::move(component)) {}void operation() override {std::cout ConcreteDecoratorA operation\n;DecoratorConcreteComponent::operation(); // 调用原始组件的操作}
};// 具体装饰器B
class ConcreteDecoratorB : public DecoratorConcreteComponent {public:explicit ConcreteDecoratorB(std::unique_ptrComponentConcreteComponent component): DecoratorConcreteComponent(std::move(component)) {}void operation() override {std::cout ConcreteDecoratorB operation\n;DecoratorConcreteComponent::operation(); // 调用原始组件的操作}
};int main() {// 创建基本组件auto component std::make_uniqueConcreteComponent();// 使用装饰器A包装组件auto decoratorA std::make_uniqueConcreteDecoratorA(std::move(component));// 使用装饰器B包装装饰器Aauto decoratorB std::make_uniqueConcreteDecoratorB(std::move(decoratorA));// 调用最终的操作decoratorB-operation();return 0;
}执行结果
ConcreteDecoratorB operation
ConcreteDecoratorA operation
ConcreteComponent operation2.7. 责任链模式的改进
责任链模式通过一系列的处理器对象来处理请求每个处理器对象可以选择处理请求或将请求传递给下一个处理器。传统的责任链模式通常使用虚函数来决定请求的处理逻辑而模板化的责任链模式通过模板和静态多态来替代虚函数。
#include iostream
#include memory// 请求类型
struct Request {int value;explicit Request(int v) : value(v) {}
};// 处理器基类
class HandlerBase {public:virtual void handleRequest(Request request) 0;void setNext(std::shared_ptrHandlerBase next) {next_ next;}protected:std::shared_ptrHandlerBase next_;
};// 具体处理器A
class ConcreteHandlerA : public HandlerBase {public:void handleRequest(Request request) override {if (request.value 10) {std::cout ConcreteHandlerA handled request with value request.value std::endl;} else if (next_) {std::cout ConcreteHandlerA passing request to next handler. std::endl;next_-handleRequest(request);}}
};// 具体处理器B
class ConcreteHandlerB : public HandlerBase {public:void handleRequest(Request request) override {if (request.value 10 request.value 20) {std::cout ConcreteHandlerB handled request with value request.value std::endl;} else if (next_) {std::cout ConcreteHandlerB passing request to next handler. std::endl;next_-handleRequest(request);}}
};// 具体处理器C
class ConcreteHandlerC : public HandlerBase {public:void handleRequest(Request request) override {std::cout ConcreteHandlerC handled request with value request.value std::endl;}
};int main() {// 创建处理器实例auto handlerA std::make_sharedConcreteHandlerA();auto handlerB std::make_sharedConcreteHandlerB();auto handlerC std::make_sharedConcreteHandlerC();// 设置责任链handlerA-setNext(handlerB);handlerB-setNext(handlerC);// 测试请求Request request1(5);handlerA-handleRequest(request1);Request request2(15);handlerA-handleRequest(request2);Request request3(25);handlerA-handleRequest(request3);return 0;
}执行结果
ConcreteHandlerA handled request with value 5
ConcreteHandlerA passing request to next handler.
ConcreteHandlerB handled request with value 15
ConcreteHandlerA passing request to next handler.
ConcreteHandlerB passing request to next handler.
ConcreteHandlerC handled request with value 25