开发一个类来测量距离,以英尺(应为
int
),英寸(应为float
)为单位。包括用于设置和获取属性的成员函数。包括构造函数。开发将两个距离相加的函数。
sum函数的原型是:
Distance Sum(Distance d);
请查看我的编码风格以及可以使该程序更好的其他方面。
#include <iostream>
using namespace std;
class Distance
{
private:
int feet;
float inch;
public:
Distance();
Distance(int a,float b);
void setDistance();
int getFeet();
float getInch();
void distanceSum(Distance d);
};
int main()
{
Distance D1,D2;
D1.setDistance();
D2.setDistance();
D1.distanceSum(D2);
return 0;
}
/*Function Definitions*/
Distance::Distance()
{
inch=feet=0;
}
Distance::Distance(int a,float b)
{
feet=a;
inch=b;
}
void Distance::setDistance()
{
cout<<"Enter distance in feet";
cin>>feet;
cout<<endl<<"Enter inches:";
cin>>inch;
}
int Distance::getFeet()
{
return feet;
}
float Distance::getInch()
{
return inch;
}
void Distance::distanceSum(Distance d)
{
cout<<"feet="<<d.feet+feet<<endl;
cout<<"inches="<<d.inch+inch<<endl;
}
#1 楼
在为程序设计类时,无论是用于家庭作业还是用于实际的生产应用程序,您都希望始终考虑该类将如何使用以及应承担的责任。每个函数和方法都应该做一件事情/任务,并且应该由方法的名称反映出来。此外,在实际开始编写代码时,您希望保持一致的易于阅读的编码风格。考虑到这两点,在代码中需要考虑一些事项:Distance::distanceSum
在这里执行两项任务。这不仅是求和英尺和英寸,但也会打印出来。
不必要的类型转换。
在默认的Distance()ctor中,存在一个隐式转换,因为您要将
0
分配给浮点类型。您应该已经从编译器得到警告。考虑使用这样的初始化列表:Distance::Distance() : feet(0), inch(0.0)
{
}
代码没有利用const正确性。
哪些参数不需要更改?哪些方法将修改您的Distance类?例如,您的
Distance::Distance(int a,float b)
并未更改a
或b
。让编译器使用const来实现承诺:Distance::Distance(const int a, const float b)
相似:
void Distance::distanceSum(const Distance &d);
缩进和间距不一致。
考虑在public下缩进方法:与private:相同。在您的作业中添加空格以提高可读性。例如。
feet = a;
没有按文件分隔的模块。
类
Distance
应该应该在单独的头文件/实现文件中,而不是将所有内容都放在一个主文件中。 /> 忍者评论。
评论?有何评论?究竟。考虑在Distance类的顶部添加一个块注释,以解释其存在的目的。块注释应该回答这样的问题,例如该类应该如何使用以及它抽象了什么细节?添加注释以阐明英尺和英寸数据成员将如何使用。例如,不清楚您的距离等级是保持相同的距离测量值,还是使用不同的单位,还是真的打算将其用作一个整体单位。例如。 6英尺2英寸还是6英尺72英寸?
基于上述考虑,这是我重构代码的一种方法:
在distance.h头文件中:
#ifndef DISTANCE_H
#define DISTANCE_H
class Distance
{
private:
// feet and inch is one unit.
// invariant: inch_ < 12.
int feet_;
float inch_;
public:
Distance(const int feet = 0, const float inches = 0.0);
void setDistance(const int feet, const float inches = 0.0);
int getFeet() const;
float getInch() const;
// returns this instance. Permits method chaining for Distance class.
Distance& Add(const Distance &d);
};
#endif
在distance.cpp实现中:
#include "distance.h"
Distance::Distance(const int feet, const float inches)
: feet_(feet + inches / 12), inch_(inches % 12)
{
}
void Distance::setDistance(const int feet, const float inches)
{
feet_ = feet + inches / 12;
inch_ = inches % 12;
}
int Distance::getFeet() const
{
return feet_;
}
float Distance::getInch() const
{
return inch_;
}
Distance& Distance::Add(const Distance &d)
{
setDistance(getFeet() + d.getFeet(), getInch() + d.getInch());
return *this;
}
以下是上面的主要更改:
距离不再将cin / cout用于显式IO。您可以将该代码放入main中。
类定义和实现现在位于它们各自的命名文件中。
通过利用默认参数删除了额外的构造函数定义。
feet和inch数据成员是一起用于表示距离测量。英寸不能大于12,因为那意味着有足够的一只脚。设置距离数据时,我们将英尺和英寸除以12来执行此操作。
const用于清楚地指示可以更改对象和不能更改距离的对象。
将distanceSum更改为Add可以更好地反映其作用。请注意,Add仅通过Distance的公共方法实现-不会直接操作
feet_
和inch_
。评论
\ $ \ begingroup \ $
为什么下划线是脚?(feet_)
\ $ \ endgroup \ $
–user1211
2011年1月31日上午8:19
\ $ \ begingroup \ $
@fahad只是我正在使用的编码约定,为类数据成员附加_。您当然可以选择适合您的其他约定。无论选择哪种方式,都要保持一致。
\ $ \ endgroup \ $
–狼人
2011年1月31日8:23
\ $ \ begingroup \ $
我认为未修改的函数参数不需要为const-我只会将函数本身标记为const。
\ $ \ endgroup \ $
– DeadMG
2011年1月31日上午9:48
\ $ \ begingroup \ $
是的,我也有同样的疑问!当通过值传递时,您无需保持其常量
\ $ \ endgroup \ $
–user1211
2011年1月31日12:50
\ $ \ begingroup \ $
const float inch = 0.0应该为0.0f,否则将进行隐式转换以从double浮起
\ $ \ endgroup \ $
– John Dibling
2011年1月31日20:40
#2 楼
没有必要同时使用英寸和英尺,因为一个可以从另一个计算出来。多余的冗余只会增加复杂性。评论
\ $ \ begingroup \ $
为什么这不是我的主要评论。尽管有很多可能的改进,如Vicors的详细解释中所提到的那样,但这还是很不错的。无论您做什么,都请先解决此问题(然后事情会变得简单得多)
\ $ \ endgroup \ $
–马丁(Martijn)
2011-2-5在0:18
\ $ \ begingroup \ $
也许是因为作业的第一句话指出,班级应该分别模拟英尺和英寸。我很久以前就学会了完成作业所要求的工作,除非我确定分频器会接受优化。
\ $ \ endgroup \ $
– David Harkness
2011-2-15在8:56
\ $ \ begingroup \ $
@David-引用为作业的文本没有这么说。
\ $ \ endgroup \ $
– anon
2011-2-15在19:31
\ $ \ begingroup \ $
@Crazy Eddie-第一句话专门说明了两个属性的数据类型:“开发一个类来测量距离,以英尺(应为int)和英寸(应为float)为单位。”第二句使用复数形式表示至少两个属性:“包括用于设置和获取属性的成员函数”。我不知道它将谈论什么其他属性。
\ $ \ endgroup \ $
– David Harkness
2011-2-15在21:33
#3 楼
其中一些函数应该是运算符。您似乎也对加法的目的感到困惑。另外,using namespace std
不好。您也没有提供任何其他运算符-即使任何类用户在逻辑上期望如果您可以添加距离,也可以向当前对象添加距离,也可以减去距离。您也没有提供任何类型的输入验证或const正确性。class Distance
{
int feet;
float inch;
public:
// Constructors
Distance();
Distance(int a, float b);
// Getters
int getFeet() const;
float getInch() const;
// Operator overloads - arithmetic
Distance operator-(const Distance&) const;
Distance& operator-=(const Distance&);
Distance operator+(const Distance&) const;
Distance& operator+=(const Distance&);
// Create from console
static Distance getDistanceFromConsole();
};
// Operator overloads - I/O
std::ostream& operator<<(std::ostream&, const Distance&);
实现是...
Distance::Distance() : feet(0), inch(0.0f) {}
Distance::Distance(int argfeet, float arginch) : feet(argfeet), inch(arginch) {
// Verify that we are actually in feet and inches.
// Not gonna write this code- dependent on the class invariants
// which were not explicitly specified (e.g., can have negative Distance?)
}
int Distance::getFeet() const {
return feet;
}
float Distance::getInch() const {
return inch;
}
Distance Distance::operator-(const Distance& dist) const {
Distance retval(*this);
retval -= dist;
return retval;
}
Distance& Distance::operator-=(const Distance& dist) {
feet -= dist.feet;
inches -= dist.inches;
// Verify values- e.g. that inches is less than 12
return *this;
}
Distance operator+(const Distance& dist) const {
Distance retval(*this);
retval += dist;
return retval;
}
Distance& operator+=(const Distance& dist) {
feet += dist.feet;
inches += dist.inches;
// More verification here.
}
std::ostream& operator<<(std::ostream& output, const Distance& dist) {
output << "Feet: " << dist.feet << "\n";
output << "Inches: " << dist.inches << std::endl; // flush when done.
return output;
}
Distance getDistanceFromConsole() {
int feet; float inch;
std::cout<<"Enter distance in feet";
std::cin>>feet;
std::cout<<endl<<"Enter inches:";
std::cin>>inch;
return Distance(feet, inch);
}
#4 楼
C ++注释:首选初始化列表:
Distance::Distance()
:feet(0), inch(0)
{
// NOT THIS -> inch=feet=0;
}
常规编码注释:
不要组合功能:
您应该定义一个函数来添加Distance对象,并打印一个对象。 (DeadMG的内容已在上面进行了介绍。)
void Distance::distanceSum(Distance d)
{
cout<<"feet="<<d.feet+feet<<endl;
cout<<"inches="<<d.inch+inch<<endl;
}
我还看到您没有将结果标准化。您可能有1英尺300.05英寸。每当对象的状态发生变化时,一个参数就会流入另一个参数,您应该对数据进行规范化。有一个明确的函数可以这样做,并在每次状态更改时调用它:
private: void Normalize() { int eFeet = inches / 12; feet += eFeet; inches -= (eFeet * 12);}
实现注释:
但是又为什么要存储实际上是两个不同变量(英尺和英寸)中的单个值。为什么不只存储总距离(以英寸为单位)(然后在进/出途中进行转换)。看unix时间。它只是计算自纪元以来的秒数。所有其他值都从此计算。
#5 楼
我也更喜欢先编写公共方法,因为当您检查大型类时,必须滚动查看公共成员。例如:
class MyClass
{
public:
// public members
protected:
// protected members
private:
// private members
}
#6 楼
您可能已经在定义方法模板的类本身中编写了方法的实现。在类中编写所有这些方法通常是一个好习惯。就您而言,即使您在类之外编写了方法,C ++编译器也会在编译时将其内联。因此,最好将这些方法编写为内联方法。这将使执行速度更快,并且将取消使用看似困难的范围解析运算符。下面是如何编写示例。它仅包含一种方法,但其余方法也可以这样做。#include <iostream>
using namespace std;
class Distance
{
private:
int feet;
float inch;
public:
Distance()
{
inch=feet=0;
}
Distance(int a,float b);
void setDistance();
int getFeet();
float getInch();
void distanceSum(Distance d);
};
int main()
{
Distance D1,D2;
D1.setDistance();
D2.setDistance();
D1.distanceSum(D2);
return 0;
}
这是更好的方法。所有的类方法都应该仅在该类中定义。
假设只用Java开发一个类,那么就不能通过这样的编写来开发一个好的类。
评论
如今,空白很便宜:不要害怕使用它。