[英]Issue with C++ constructor
编辑:这个问题出现了,我想我已经开始了! 去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 ,请参阅Rectangle
getArea()
。 当我删除它告诉我它“无法实例化抽象类”。 那是什么意思?
编辑:这是主要的:
void main (void)
{
Rectangle rect1 ("blue",5,6);
Rectangle *prect2 = new Rectangle("red",5,6);
rect1.setColour("red");
rect1.printDetails();
prect2->printDetails();
}
我没有看到任何错误,但你可以通过使用初始化列表使其更有效(否则你的两个类的私有成员初始化两次):
Rectangle::Rectangle(string col, int len, int br)
: Polygon(col), length(len), breadth(br)
{
}
请注意,初始化列表也可以调用Polygon的构造函数。
请参阅为什么我更喜欢使用成员初始化列表? 有关使用初始化列表的优点的完整描述。
如果它是关于最佳C ++实践,那么:
我唯一看到的是有两个printDetails()但是基类一个不是虚拟的,所以你不会得到预期的多态行为。
我看到的主要“问题”(它有点小)是派生的构造函数让父类使用其默认的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) {};
对于每个调用为2的Rectangle
构造函数,此公式将从4 std::string
构造(和3个析构)中获取。通过对Polygon
构造函数进行相同的更改,可以进一步将其转换为1。
您应该使用col参数调用基础构造函数:
Rectangle::Rectangle(string col, int len, int br) : Polygon(col)
{
//setColour(col);
length =len;
breadth=br;
}
关于getArea() :
删除它时它不编译的原因是因为该函数在您的Polygon类virtual double getArea()=0;
被标记为纯虚拟 virtual double getArea()=0;
使用=0
;
对于关于Rectangle::getArea()
PS: virtual double getArea()=0;
多边形声明virtual double getArea()=0;
表示该函数是纯虚函数 。 您可以从概念上考虑这一点:“所有多边形都有一个区域,所以我应该能够问它是什么,但除非多边形具有特定类型(方形,圆形),否则它将不知道它的区域是什么”。
这意味着您的Polygon类是一个抽象类。 通过不在Rectangle类中定义getArea()
,您的矩形类也是一个抽象类。 您无法实例化Rectangle,因为编译器不知道任何Rectangle::getArea()
函数定义。
您还可以在初始化列表中添加对基类构造函数的调用:
Rectangle::Rectangle(string col, int len, int br)
: Polygon(col), length(len), breadth(br)
它使用基类的构造函数,所以有点整洁。
我可以在这里想到一些可能的问题:
使用初始化列表分配值。
调用基类构造函数来设置颜色。
字符串可能不是表示颜色的最佳类型。 也许枚举或单独的颜色类在这里会更好。 如果操作正确,这也可以防止传递无效颜色。
说到无效值 :长度和宽度应该在构造函数中验证(你不想最终得到负面区域,是吗?)。 至少使用一个断言 。 它对发布版本没有影响,但可以防止开发错误。 对于更公开的界面, 例外也可能是一种选择(这在某种程度上是个人品味)。
如果你真的想使用字符串作为颜色,请通过const引用传递它(并且可能测试边缘情况,如空字符串)。
printDetails
应该是虚拟的 ,因此您可以使用基类指针调用它。 当前实现可能不会按预期运行。
该类似乎是为多态性而设计的。 如果需要从基类指针中删除,则必须定义虚拟析构函数 。 由于已经存在虚拟方法,因此它也可能不会受到影响。
getArea
和printDetails
应声明为const ,以便可以在const对象上调用它们。 他们不应该修改对象。
这只是一个可能性列表。 他们中的许多人依赖于课程的预期用途而可能不需要,但仔细考虑它们并没有什么坏处。
如上所述,printDetails将不会按预期运行。
我也认为只是在Rectangle类中声明getArea()有点欺骗,因为你没有为它提供实现,如果你碰巧在你的代码中调用它,你会得到一个链接器错误。
初始化顺序问题是可能的。 Polygon :: setColour可以调用纯虚拟的Polygon :: getArea 。 (没有迹象表明它需要,但存在可能性。)Rectangle中的实现可能需要长度和宽度来计算区域,但它们尚未初始化。
最小的修复是在调用setColour之前初始化长度和宽度 :
Rectangle::Rectangle(string col, int len, int br)
{
length =len;
breadth=br;
setColour(col);
}
当然,最好从Polygon中删除pure virtual getArea()
声明,因为任何Polygon方法似乎都不需要它。 但这超出了问题的范围。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.