编辑:这个问题出现了,我想我已经开始了!去StackOverflow !! :d
我的考试即将开始,去年考试的一个问题是发现以下构造函数的实现问题并编写更正的考试。
Rectangle::Rectangle(string col, int len, int br)
{
setColour(col);
length =len;
breadth=br;
}
类定义如下:
class Polygon
{
public:
Polygon(string col="red");
void printDetails(); // prints colour only
virtual double getArea()=0;
void setColour(string col);
private:
string colour;
};
class Rectangle : public Polygon
{
public:
Rectangle(string, int, int);
void printDetails(); // prints colour and area
// for part 3, delete the line below
double getArea();
private:
int length;
int breadth;
};
我已将代码编写到编译器中,运行正常。我猜这个问题与继承有关,因为string colour;
是私有的,但setColour
是公开的,所以我无法弄明白。除非它Rectangle::Rectangle(string col, int len, int br):length(len), breadth(br)
然后在construcor或其他内部设置颜色。
它唯一值得3分,所以如果没有人想回答它就没什么大不了的,但我想如果我将有一个程序员的职业生涯,我尽可能多地了解它。 ;)
感谢您的帮助。
PS ,请参阅getArea()
中的Rectangle
。当我删除它告诉我它“无法实例化抽象类”。这是什么意思?
编辑:这是主要的:
void main (void)
{
Rectangle rect1 ("blue",5,6);
Rectangle *prect2 = new Rectangle("red",5,6);
rect1.setColour("red");
rect1.printDetails();
prect2->printDetails();
}
答案 0 :(得分:23)
我没有看到任何错误,但是你可以通过使用初始化列表来提高效率(否则你的两个类的私有成员会被初始化两次):
Rectangle::Rectangle(string col, int len, int br)
: Polygon(col), length(len), breadth(br)
{
}
请注意,初始化列表也可以调用Polygon的构造函数。
有关使用初始化列表的优点的完整说明,请参阅Why should I prefer to use member initialization list?。
答案 1 :(得分:10)
如果是关于最佳C ++实践,那么:
答案 2 :(得分:9)
我唯一看到的是有两个printDetails(),但是基类一个不是虚拟的,所以你不会得到预期的多态行为。
答案 3 :(得分:7)
我看到的主要“问题”(并且它有点小)是派生的构造函数让父类使用其默认的colo(u)r值(“red”),然后提供它自己的。这有点浪费,当你可以从一开始就给它正确的那个。
Rectangle::Rectangle(string col, int len, int br) : Polygon(col) {
length =len;
breadth=br;
};
现在,完成上述操作后,您可以通过以下方式初始化所有成员:
Rectangle::Rectangle(string col, int len, int br)
: Polygon(col), length(len), breadth(br) {};
嗯。现在我看看这个,还有另外一个问题。您的构造函数通过复制传递std::string
个对象,而不是修改它们。这也是一种浪费。所有构造函数string
参数都应更改为string const &
个参数。这可能会避免在运行时对字符串进行额外的复制构造,并通知编译器和用户您实际上没有修改输入字符串(这实际上并非如此)。
所以最终版本看起来更像是:
Rectangle::Rectangle(string const & col, int len, int br)
: Polygon(col), length(len), breadth(br) {};
这个公式为你带来4个std::string
构造(和3个析构),每个Rectangle
构造函数调用为2。通过对{{进行相同的更改,可以进一步将其归结为1。 1}}构造函数。
答案 4 :(得分:6)
您应该使用col参数调用基础构造函数:
Rectangle::Rectangle(string col, int len, int br) : Polygon(col)
{
//setColour(col);
length =len;
breadth=br;
}
关于 getArea():
删除它时无法编译的原因是因为该函数在使用virtual double getArea()=0;
的多边形类=0
中标记为pure virtual;
答案 5 :(得分:3)
对于关于Rectangle::getArea()
的PS:在virtual double getArea()=0;
的多边形声明表示该函数是pure virtual function。您可以从概念上考虑这一点:“所有多边形都有一个区域,所以我应该能够问它是什么,但除非多边形具有特定类型(方形,圆形),否则它将不知道它的区域是什么”。
这意味着您的Polygon类是一个抽象类。通过不在Rectangle类中定义getArea()
,您的矩形类也是一个抽象类。您无法实例化Rectangle,因为编译器不知道任何Rectangle::getArea()
函数定义。
答案 6 :(得分:2)
您还可以在初始化列表中添加对基类构造函数的调用:
Rectangle::Rectangle(string col, int len, int br)
: Polygon(col), length(len), breadth(br)
它使用基类的构造函数,所以有点整洁。
答案 7 :(得分:2)
我可以在这里想到一些可能的问题:
使用初始化列表分配值。
调用基类构造函数来设置颜色。
字符串可能不是表示颜色的最佳类型。也许 enum 或单独的颜色类会更好。如果操作正确,这也可以防止传递无效颜色。
说到无效值:长度和广度应该在构造函数中验证(你不想最终得到负面区域,是吗?)。至少使用断言。它对发布版本没有影响,但可以防止开发错误。对于更公开的界面,例外也可能是一种选择(这在某种程度上是个人品味)。
如果你真的想使用字符串作为颜色,请通过 const reference 传递它(并且可能测试空字符串等边缘情况)。
printDetails
应该是虚拟,因此您可以使用基类指针调用它。当前的实现可能不会按预期运行。
该类似乎是为多态性而设计的。如果需要从基类指针中删除,则必须定义虚拟析构函数。由于已经存在虚拟方法,因此它也可能不会受到影响。
getArea
和printDetails
应声明为 const ,以便可以在const对象上调用它们。他们不应该修改对象。
这只是一系列可能性。他们中的许多人依赖于课程的预期用途,可能不需要,但仔细考虑它们并没有什么坏处。
答案 8 :(得分:1)
如上所述,printDetails的行为不会如预期的那样 我也认为只是在Rectangle类中声明getArea()有点欺骗,因为你没有为它提供实现,如果你碰巧在你的代码中调用它,你会得到一个链接器错误。
答案 9 :(得分:0)
初始化订单问题是可能的。 Polygon :: setColour 可以调用纯虚拟 Polygon :: getArea 。 (没有迹象表明它需要,但存在可能性。)Rectangle中的实现可能需要 length 和 widthth 来计算区域,但它们不是初始化了。
最小修复是在调用 setColour 之前初始化长度和广度:
Rectangle::Rectangle(string col, int len, int br)
{
length =len;
breadth=br;
setColour(col);
}
当然,最好从Polygon中删除pure virtual getArea()
声明,因为任何Polygon方法似乎都不需要它。但这超出了问题的范围。