糟糕,我正要完全重新设计我的答案,但你接受了。
但是好的,请考虑以下作为附加信息。
“我正在考虑制作 shell 和 leg 类模板,它们的父类型将是模板参数。”
一般来说,这种设计模式被称为 Curiously recurring template Pattern,可以很好地替代动态多态性(运行时类型检查)。
如果您的用例只需要在编译时构建这些实例,您可以直接使用这种方式。
考虑一个legs 类模板,它为具体类提供已知数量的腿
class leg : public node {
public:
void moveForward(int speed) {
// Any behavioral implementation
}
};
template<class Impl, size_t LegsCount>
class legs {
public:
// Provide a public interface to interact with legs
void moveForward(size_t legIndex) {
// Delegate behavioral implementation to Impl
self->doMoveForward(legIndex);
}
size_t getLegsCount() const { return LegsCount; }
// eventually provide a default behavior that can be called from
// classes implementing the interface
void doMoveForward(size_t legIndex) {
if(legIndex >= LegsCount) {
throw std::out_of_range();
}
}
protected:
legs(const std::array<const std::array<leg,LegsCount>& legs)
: self(static_cast<Impl>(self))
, legs_(legs) {
}
private:
Impl* self;
std::array<leg,LegsCount> legs_;
};
进一步考虑具有某些特征的 shell 类
struct shell_base {
const bool CanOpenShell;
virtual void openShell() = 0;
shell_traits(bool canOpen = false) : CanOpenShell(canOpen) {}
};
template<class Impl>
class shell : public shell_base {
public:
// Provide a public interface to interact with legs
void openShell() {
if(CanOpenShell) {
// Check if the operation is applicable
if(!CanOpenShell) {
throw std::domain_error("Can't open shell.");
}
// Delegate behavioral implementation to Impl
self->doOpenShell();
}
}
void doOpenShell() {
}
protected:
shell(bool canOpen) : shell_traits(canOpen) {
}
};
你的类声明将如下所示
class turtle
: public node
, public legs<turtle,4>
, public shell<turtle> {
public:
turtle()
: legs<turtle,4>({leg(),leg(),leg(),leg()})
, shell<turtle>(false) {
}
void doMoveForward(size_t legIndex) {
// Let the base implementation check the range first
legs<turtle,4>::doMoveForward(legIndex);
// Call the specific behavior
legs_[legIndex]->moveForward(10); // at slow speed
}
};
class clam
: public node
, public shell<clam> {
public:
clam() : shell<clam>(true) {
}
void doOpenShell() {
// Implementation
}
};
class dog
: public node
, public legs<dog,4> {
public:
dog() : legs<dog,4>({leg(),leg(),leg(),leg()}) {
}
void doMoveForward(size_t legIndex) {
// Let the base implementation check the range first
legs<dog,4>::doMoveForward(legIndex);
// Call the specific behavior
legs_[legIndex]->moveForward(100); // at fast speed
}
};