假设我们有一个抽象类Element
,派生类Triangle
和Quadrilateral
。
假设这些类与依赖于元素形状的插值方法一起使用。所以,基本上我们创建了一个抽象类InterpolationElement
,我们从中派生InterpolationTriangle
和InterpolationQuadrilateral
。
然后,要在Triangle
和Quadrilateral
类中包含插值功能,我们在类型Element
的类InterpolationElement
中添加一个const-reference数据成员,即:
class Element
{
public:
Element(const InterpolationElement& interp);
const InterpolationElement& getInterpolation() const;
private:
const InterpolationElement& interpolation;
};
然后我们创建一个方法(如Scott Meyers所述,Effective C ++),将类InterpolationTriangle
的本地静态对象实例化为
const InterpolationTriangle& getInterpolationTriangle()
{
static InterpolationTriangle interpolationTriangle;
return interpolationTriangle;
}
因此,类Triangle
可以构造为:
class Triangle : public Element
{
public:
Triangle() : Element( getInterpolationTriangle() ) {}
};
这是我的问题:这种方法是否正确,以便在我的班级Element
中加入插值方法?这是在专业场景中使用的吗?
我可以直接在类Element
上实现所有插值方法(作为纯虚拟),并在派生类Triangle
和Quadrilateral
中覆盖它们。然而,这种方法在我看来很麻烦,因为每次我需要改进或实现新的插值功能时,我都必须在这些类上做到这一点。而且,使用这种方法,类越来越大(许多方法)。
我想听听您的一些提示和意见
提前致谢。
其他详情:
class InterpolationElement
{
public:
InterpolationElement();
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
}
class InterpolationTriangle : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
class InterpolationQuadrilateral : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
:
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
}
答案 0 :(得分:1)
这些类与插值方法一起使用。为什么这些方法需要在单个对象中?这里的单身人士看起来很成问题。
class Element
{
public:
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
};
class Triangle : public Element
{
public:
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
另外,欢迎来到SO!
答案 1 :(得分:1)
这让我想起了我回答here的问题。关于数据容器和策略分离的相同想法。
答案 2 :(得分:1)
您的提案存在一个小问题:您已向基类添加了插值相关方法,并且您已更改了构造函数...
首先,如果您希望这样做,请按照以下方式进行:
class Element
{
public:
private:
// similar signature to a `clone` method
virtual InterpolationElement* interpolation() const = 0;
};
class Triangle
{
public:
private:
virtual InterpolationTriangle* interpolation() const
{
return new InterpolationTriangle();
}
};
这里有两个优点:
const
,它允许它在计算过程中保持状态......就像对正在插入的当前对象的引用一样。但是,这仍然需要更改Element
类及其每个派生类。难道不打扰你;)?
嗯,是时候(一次)调用设计模式:Visitor
。
与战略理念略有不同,依靠双重派遣才能正常运作。但是,它允许您调整Element
的ONCE(使用accept
方法)的层次结构,然后根据需要添加任意数量的操作。这很棒。
答案 3 :(得分:1)
你总是可以用模板搞砸一下。 首先,我们有一流的。
class Element {
public:
virtual void calculate() const = 0;
};
...但是我们在层次结构中间也有一个类,它实际上是一个模板。模板不能是顶级类,因为具有不同参数的模板是不同的类。我们的想法是,我们将插值类作为元素的类型参数。
template <typename Interpolation>
class Element_Impl : public Element {
protected:
Interpolation m_interpolation;
};
插值类。请注意,他们不是兄弟姐妹,因为他们不需要。
class InterpolationTriangle {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
最后是真实的元素和小的主要程序。
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
m_interpolation.interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
m_interpolation.interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
摘要:
一种方法是使用静态方法,并在Element_Impl中定义一个包装器 - 仍然只在一个地方。
class Element {
public:
virtual void calculate() const = 0;
};
template <typename Interpolation>
class Element_Impl : public Element {
protected:
void interpolate(double, double) const {
Interpolation::interpolate(1, 1);
}
};
class InterpolationTriangle {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
答案 4 :(得分:1)
我首先想到的是GoF Design Pattern Visitor
根据我对你的问题的理解,这个模式被设想为完全解决这个问题。
每个Visitor对象定义一种插值技术或应用于对象的算法。
因此,Element类不会随着每个新的functionnality而增长。一旦到位,访问者模式就可以丰富功能,而无需触及基类定义。