Fra*_*ank 37 c++ templates abstract-class design-patterns virtual-functions
如果我想使类适应,并且可以从外部选择不同的算法 - C++中最好的实现是什么?
我主要看到两种可能性:
这是一个小例子,在各种版本中实现:
版本1:抽象基类
class Brake {
public: virtual void stopCar() = 0;
};
class BrakeWithABS : public Brake {
public: void stopCar() { ... }
};
class Car {
Brake* _brake;
public:
Car(Brake* brake) : _brake(brake) { brake->stopCar(); }
};
Run Code Online (Sandbox Code Playgroud)
版本2a:模板
template<class Brake>
class Car {
Brake brake;
public:
Car(){ brake.stopCar(); }
};
Run Code Online (Sandbox Code Playgroud)
版本2b:模板和私有继承
template<class Brake>
class Car : private Brake {
using Brake::stopCar;
public:
Car(){ stopCar(); }
};
Run Code Online (Sandbox Code Playgroud)
来自Java,我自然倾向于始终使用版本1,但模板版本似乎经常是首选,例如在STL代码中?如果这是真的,是因为内存效率等(没有继承,没有虚函数调用)?
我意识到版本2a和2b之间没有太大的区别,请参阅C++ FAQ.
你能评论一下这些可能吗?
Joh*_*itb 33
这取决于你的目标.如果您可以使用版本1
我通常更喜欢使用运行时多态性的版本1,因为它仍然是灵活的,并允许您使Car仍具有相同的类型:Car<Opel>是另一种类型Car<Nissan>.如果你经常使用制动器时你的目标很棒,我建议你使用模板化的方法.顺便说一句,这称为基于策略的设计.你提供制动政策.例子,因为你说你用Java编程,可能你还不熟悉C++.一种方法:
template<typename Accelerator, typename Brakes>
class Car {
Accelerator accelerator;
Brakes brakes;
public:
void brake() {
brakes.brake();
}
}
Run Code Online (Sandbox Code Playgroud)
如果您有很多策略,可以将它们组合到自己的结构中,然后传递它,例如作为SpeedConfiguration收集Accelerator,Brakes还有更多.在我的项目中,我尝试保留大量无代码模板,允许将它们编译成自己的目标文件,而不需要在头文件中使用代码,但仍然允许多态(通过虚函数).例如,您可能希望保留非模板代码可能在基类中多次调用的常见数据和函数:
class VehicleBase {
protected:
std::string model;
std::string manufacturer;
// ...
public:
~VehicleBase() { }
virtual bool checkHealth() = 0;
};
template<typename Accelerator, typename Breaks>
class Car : public VehicleBase {
Accelerator accelerator;
Breaks breaks;
// ...
virtual bool checkHealth() { ... }
};
Run Code Online (Sandbox Code Playgroud)
顺便说一下,这也是C++流使用的方法:std::ios_base包含不依赖于char类型的标志和东西,或者像openmode,format flags和stuff这样的特性,std::basic_ios然后是继承它的类模板.这还通过共享类模板的所有实例化所共有的代码来减少代码膨胀.
一般应避免私人继承.它在很少有用,在大多数情况下,遏制是一个更好的主意.通常情况下,当size非常重要时,情况正好相反(例如,基于策略的字符串类):从空策略类(仅包含函数)派生时,可以应用空基类优化.
Nem*_*vic 32
经验法则是:
1)如果在编译时选择具体类型,则更喜欢模板.它会更安全(编译时错误与运行时错误)并且可能更好地优化.2)如果选择是在运行时进行的(即由于用户的操作),则实际上没有选择 - 使用继承和虚函数.
| 归档时间: |
|
| 查看次数: |
16453 次 |
| 最近记录: |