题
我最近编写了一个渲染 B 样条曲线的类。这些曲线由许多控制点定义。最初,我打算使用八个控制点,所以我在类中添加了一个常量,如下所示:
class Curve
{
public:
static const int CONTROL_POINT_COUNT = 8;
};
现在我想扩展这个类以允许任意数量的控制点。所以我想将其更改为:
class Curve
{
public:
int getControlPointCount() {return _controlPointCount;}
};
问题是,为了提高适应性,一开始就将常量存储在方法中是否不是更好。换句话说,这样开始不是更好吗:
class Curve
{
public:
int getControlPointCount() {return 8;}
};
这样做的优点是我可以只更改相关方法中的一个符号,而不是移动常量等。
这是一种好的做法还是一种坏的做法?
解决方案
通常我喜欢手动保持尽可能少的耦合成为可能。
在曲线控制点的数量是,那么,在曲线的控制点的数目。这并不是说可以随意设置一个独立的变量。
所以我通常会暴露一个const标准集装箱参考:
class Curve
{
private:
std::vector<Point>& _controlPoints;
public:
Curve ( const std::vector<Point>& controlPoints) : _controlPoints(controlPoints)
{
}
const std::vector<Point>& getControlPoints ()
{
return _controlPoints;
}
};
如果你想知道的许多控制点如何,然后使用curve.getControlPoints().size()
。我怀疑,在大多数的使用情况下,你想要的点以及伯爵无论如何,和暴露标准容器,你可以使用标准库的迭代成语和内置算法,而得到计数并调用就像在一个循环getControlPointWithIndex
的功能。
如果真的有什么其他的曲线类,我甚至去尽量为:
typedef std::vector<Point> Curve;
(通常是一个曲线将不会呈现本身,作为一个渲染器类可具有约渲染管线细节,留下一个曲线作为纯粹的几何伪影)
其他提示
int getControlPointCount() {return _controlPointCount;}
这是一个存取。交换为访问一个const静是不是一个真正的增益litb指出。你真的需要什么的面向未来的的可能是一对访问和突变的。
int getControlPointCount() {return _controlPointCount;} // accessor
我还扔在一个设计常数的访问,使其:
int getControlPointCount() const {return _controlPointCount;} // accessor
和相应的:
void setControlPointCount(int cpc) { _controlPointCount = cpc;} //mutator
现在,用静态对象的大的区别在于,控制点数量不再是类级别属性,但一个实例平1。这是一个设计变化。你要这样说?
尼特:的你的职业等级的静态数为public
,因此并不需要一个访问
要更好地回答你的问题,你也应该知道controlPointCount变量的设置。它与你的类设置之外?在这种情况下,你也应该定义一个setter。或曲线类是唯一负责设置呢?难道只有在编译的时候还是也可以在运行时设置。
总之,避免即使在这种形式的幻数:
int getControlPointCount() {return 8;}
这是更好的:
int getControlPointCount() {return CONTROL_POINT_COUNT;}
一个方法具有的优点是可以修改的内部实现(使用一个恒定值,从配置文件中读出,动态地改变的值),而不会影响外部的类。
class Curve
{
private:
int _controlPointCount;
void setControlPointCount(int cpc_arg)
{
_controlPointCount = cpc_arg;
}
public:
curve()
{
_controlPointCount = 8;
}
int getControlPointCount() const
{
return _controlPointCount;
}
};
我将创建一个这样的代码,在私人设置功能,让没有任何机构可以与对照点数玩,直到我们移动到development..where下一阶段我们更新开始在更新控制点数运行。在那个时候,我们可以从私人移动这套方法公开范围。
在理解这个问题的同时,我对这个例子有一些概念上的问题:
- 返回值是多少
getControlPointCount()
什么时候控制点的数量不受限制?- 是 MAXINT 吗?
- 它是曲线上当前控制点的数量(从而打破了这是最大可能点数的逻辑?)
- 当您实际尝试创建具有 MAXINT 点的曲线时会发生什么?你最终会耗尽内存。
界面本身对我来说似乎有问题。与其他标准集合类一样,该类应该封装其对点数的限制以及其 AddControlPoint()
如果发生大小、内存限制或任何其他违规,则应返回错误。
至于具体的答案,我同意kgiannakakis的观点:成员函数允许更大的灵活性。
我倾向于通过程序的执行用于所有“稳定”值的配置+常数(默认值)。与该不能改变值平原常数(360度 - > pi第2弧度60秒 - > 1分钟)或它的变化会破坏运行代码(最小/最大值为算法,使它们不稳定)
。您在处理一些不同的设计问题。首先,你必须知道的控制点的数量是一个类或实例级别的值。然后,无论是在任何两个层面的恒定。
如果所有的曲线必须在应用程序共享相同的数目的控制点则是一类电平(静态)值。如果不同的曲线可以有不同数量的控制点,那么它是不是一类的电平值,而是一个实例级的一个。
在这种情况下,如果控制点的数量将所述曲线的整个寿命期间是恒定的,然后它是一个实例级恒定,如果它可以改变那么它是不是在这个水平是恒定的。
// Assuming that different curves can have different
// number of control points, but that the value cannot
// change dynamically for a curve.
class Curve
{
public:
explicit Curve( int control_points )
: control_points_( control_points )
{}
// ...
private:
const int control_points_;
};
namespace constant
{
const int spline_control_points = 8;
}
class Config
{
public:
Config();
void readFile( std::string const & file );
// returns the configured value for SplineControlPoints or
// constant::spline_control_points if the option does not
// appear in config.
int getSplineControlPoints() const;
};
int main()
{
Config config;
config.readFile( "~/.configuration" ); // read config
Curve c( config.getSplineControlPoints() );
}
有关积分型我usualy使用:
class Curve
{
public:
enum
{
CONTROL_POINT_COUNT = 8
};
};
如果常量并不需要对除类实现的任何实体,我宣布在* .cpp文件常量。
namespace
{
const int CONTROL_POINT_COUNT = 8;
}
在一般情况下,所有的数据应该是私有的,并通过getter和setter方法访问。否则,你违反了封装。即,如果你暴露下面的数据你自己锁和类成基本数据的特定表示。
在这种特殊情况下我会做我觉得像下面这样:
class Curve
{
protected:
int getControlPointCount() {return _controlPointCount;}
int setControlPointCount(int c) { _controlPointCount = c; }
private:
static int _controlPointCount = 0;
};
在一般常量不应内部的方法来定义。你选择的例子有两个独特的功能。首先,它是一个getter;第二,正在返回的类型是一个整数。但是,在定义常量的一点就是使用他们不止一次,并且能够引用它们的便捷途径。键入“8”,而不是“controlPointCount”可以节省您的时间,并可能似乎没有招致维护成本,但是这通常不会是真实的,如果你总是里面定义常量的方法。