我正在为当前的设计而苦苦挣扎,想知道是否有可能在不使用转换方法的情况下决定调用哪个方法。假设我有一个基础 Fence
类。
目前,我的 worker 知道如何 build 木栅栏以及如何 build 倒钩铁丝网。他们可以将两个栅栏加在一起……但到目前为止,他们只学会了如何将木栅栏与木栅栏连接起来,以及如何将带倒钩的有线的与带倒钩的有线的连接起来。
但是他们可能会学到更多,Fence 类有一个虚拟的 addFence(const Fence& fence)
方法。
因为我想避免任何转换方法,所以我尝试在两个类中添加特殊的 addFence()
方法。这是一个例子:
class Fence {
public:
virtual void addFence(const Fence& fence) = 0;
...
};
class BarbWireFence : public Fence {
public:
...
void addFence(const Fence& fence) {
//only add such a fence, if it is a barb wired one
}
void addFence(const BarbWireFence& fence) {
//continue the fence with the given one
}
};
class WoodenFence : public Fence {
public:
...
void addFence(const Fence& fence) {
//only add the fence, if it is a wooden one
}
void addFence(const WoodenFence& fence) {
//continue the fence with the given one
}
};
现在我想做类似的事情
Fence *woodenFence1 = new WoodenFence();
Fence *woodenFence2 = new WoodenFence();
woodenFence1->addFence(*woodenFence2);
但由于运行时决定我有什么样的栅栏,我只有基本 Fence*
指针以及基本 class Fence
的定义用于最后一行。
那么有没有更好的实现来“自动”决定我有什么样的围栏?还是我应该使用完全不同的设计?
最佳答案
欢迎来到binary methods的精彩世界| .
这个问题没有令人满意的解决方案。您可能想了解 double dispatch和它更正式的兄弟the Visitor pattern .这两件事基本上是一样的,只是呈现方式略有不同。在最简单的情况下,您可以这样做:
class WoodenFence;
class BarbWireFence;
class Fence {
public:
virtual void addFence(const Fence& fence) = 0;
virtual void addMe(BarbWireFence& fence) const = 0;
virtual void addMe(WoodenFence& fence) const = 0;
...
};
class BarbWireFence : public Fence {
public:
...
void addFence(const Fence& fence) {
fence->addMe(*this);
}
void addMe(BarbWireFence& fence) const {
fence->addBarbWireFence(*this);
}
void addMe(WoodenFence& fence) const {
throw error("bad fence combo");
}
void addBarbWireFence(const BarbWireFence& fence) {
// actually add fence...
}
};
class WoodenFence : public Fence {
public:
...
void addFence(const Fence& fence) {
fence->addMe(*this);
}
void addMe(BarbWireFence& fence) const {
throw error("bad fence combo");
}
void addMe(WoodenFence& fence) const {
fence->addWoodenFenceFence(*this);
}
void addWoodenFence(const WoodenFence& fence) {
// actually add fence...
}
...
};
您可以想出当您添加 10 种其他栅栏类型时会发生什么。
人们可能会采取完全不同的方向,即模板化整个业务并摆脱 Fence 基类,因为它不提供类型安全的接口(interface)。
class BarbWireFence {
public:
...
void addSimilarFence(const BarbWireFence& fence) {
//continue the fence with the given one
}
};
class WoodenFence {
public:
...
void addSimilarFence(const WoodenFence& fence) {
//continue the fence with the given one
}
};
template <typename Fence>
void addFence (Fence& f1, const Fence& f2) {
f1->addSimilarFence(f2);
}
关于c++ - 决定将哪个派生类作为参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26590251/