繁体   English   中英

C ++构造函数的问题

[英]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 ++实践,那么:

  1. 通过const引用传递字符串参数;
  2. 使用初始化列表并通过将颜色传递给父构造函数而不是setColour来初始化颜色。

我唯一看到的是有两个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)

它使用基类的构造函数,所以有点整洁。

我可以在这里想到一些可能的问题:

  1. 使用初始化列表分配值。

  2. 调用基类构造函数来设置颜色。

  3. 字符串可能不是表示颜色的最佳类型。 也许枚举或单独的颜色类在这里会更好。 如果操作正确,这也可以防止传递无效颜色。

  4. 说到无效值 :长度和宽度应该在构造函数中验证(你不想最终得到负面区域,是吗?)。 至少使用一个断言 它对发布版本没有影响,但可以防止开发错误。 对于更公开的界面, 例外也可能是一种选择(这在某种程度上是个人品味)。

  5. 如果你真的想使用字符串作为颜色,请通过const引用传递它(并且可能测试边缘情况,如空字符串)。

  6. printDetails应该是虚拟的 ,因此您可以使用基类指针调用它。 当前实现可能不会按预期运行。

  7. 该类似乎是为多态性而设计的。 如果需要从基类指针中删除,则必须定义虚拟析构函数 由于已经存在虚拟方法,因此它也可能不会受到影响。

  8. getAreaprintDetails应声明为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM