我阅读了Herb Sutter的文章http://www.gotw.ca/publications/mill18.htm,其中涉及虚函数以及默认情况下应如何将其声明为私有。公开虚拟函数将使其用作接口和定制器,并且建议将接口与定制行为分开,如本文所述。
class shape
{
protected:
void set_area(double area)
{
area = area;
};
private:
double area;
virtual void compute_area() = 0;
};
class square
{
private:
double length;
void compute_area()
{
set_area(length*length);
}
};
[如果我们考虑这些类,我们将看到我们永远不能从任何一个类的外部调用area函数,因为它们被设计为虚拟的,因为我们不希望虚拟函数充当该类与“外界建议”。如果我正确理解他,请使用模板方法,并且要计算shape
对象的面积,则需要为shape
类提供一个公共的非虚函数。像这样吗?
class shape
{
public:
void interfacer()
{
compute_area();
}
protected:
void set_area(double area)
{
area = area;
};
private:
double area;
virtual void compute_area() = 0;
}
似乎仅仅能够做到这一点似乎并不多余:
shape *ptr = new square();
ptr->compute_area();
如果我们要公开虚拟功能?
我重新阅读了这篇文章,他说公共虚拟对象应该“很少使用”。我想知道他是否认为上述情况是将虚拟函数公开而不是私有的例子之一。
您正确理解。您必须提供一个调用该虚函数的公共非虚函数。
您似乎在问这是什么意思:为什么用户调用一个调用私有实现的公共功能,而不是仅仅拥有一个可以正常工作的功能?赫伯在帖子中回答了这个问题:
首先,请注意,基类现在可以完全控制其接口和策略,并且可以在一个方便的可重用位置(非虚拟接口功能)中强制执行接口的先决条件和后置条件,插入检测以及执行任何类似的工作。 ...
第二,当我们更好地将接口和实现分开时,我们可以自由地使每个接口都采用其自然希望采用的形式,而不是试图找到迫使它们看起来相同的折衷方案。例如,...
第三,面对变化,基类现在已经不那么脆弱了。以后我们可以自由地改变主意,添加前置条件和后置条件检查,或者将处理分为更多步骤,或者重构,或者使用Pimpl习惯用法[4]实现更完整的接口/实现分离,或者对Widget的可定制性进行其他修改,而不影响使用Widget的代码。 ...
通常,编写适当分解的代码的许多好处只有到了使代码变得更复杂的时候才会真正显现出来。