C++ 与C+的问题+;建造师

C++ 与C+的问题+;建造师,c++,constructor,C++,Constructor,编辑:这个问题出现了,我想我得了A!加油!!:D 我马上就要考试了,去年考试中的一个问题是发现以下构造函数的实现问题,并编写一个更正的构造函数 Rectangle::Rectangle(string col, int len, int br) { setColour(col); length =len; breadth=br; } 类别定义如下: class Polygon { public: Polygon(string col="red"); voi

编辑:这个问题出现了,我想我得了A!加油!!: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;
};
我已经把代码写进了编译器,它运行得很好。我猜这个问题与继承有关,因为
字符串颜色
是私有的,但是
setcolor
是公共的,所以我想不出来。除非它的
Rectangle::Rectangle(字符串col,int len,int br):长度(len),宽度(br)
,然后在construcor内设置颜色或其他

它只值3分,所以如果没有人愿意回答,这没什么大不了的,但我想,如果我想成为一名程序员,我的兴趣是尽可能多地了解。)

谢谢你的帮助

PS,请参见
矩形中的
getArea()
。当我删除它时,它告诉我它“无法实例化抽象类”。这是什么意思

编辑:主要内容如下:

void main (void)
{
    Rectangle rect1 ("blue",5,6);
    Rectangle *prect2 = new Rectangle("red",5,6);
    rect1.setColour("red");
    rect1.printDetails();
    prect2->printDetails();
}

我看到的唯一一件事是有两个printDetails(),但基类一不是虚拟的,因此您不会得到预期的多态行为

我没有发现任何错误,不过您可以通过使用初始化列表来提高效率(否则两个类的私有成员都会被初始化两次):

请注意,初始化列表也可以调用多边形的构造函数


有关使用初始化列表优点的完整说明,请参阅。

您应该使用col参数调用基本构造函数:

Rectangle::Rectangle(string col, int len, int br) : Polygon(col)
{
    //setColour(col);
    length =len;
    breadth=br;
}
关于getArea()

当您删除它时,它不会编译的原因是,该函数被标记为在您的多边形类
virtual double getArea()=0中使用
=0

您还可以在初始值设定项列表中添加对基类构造函数的调用:

Rectangle::Rectangle(string col, int len, int br)
    : Polygon(col), length(len), breadth(br)
这使用了基类的构造函数,所以有点整洁。

我看到的主要“问题”是派生构造函数允许父类使用其默认的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个析构函数)到2个。通过对多边形> /COD>构造函数进行相同的修改,可以进一步降低到一个。

< P>如果是关于C++的最佳实践,那么:

  • 通过常量引用传递字符串参数
  • 使用初始值设定项列表并通过将颜色传递给父构造函数(而不是SetColor)来初始化颜色

  • 关于
    Rectangle::getArea()
    :在多边形中声明
    虚拟双getArea()=0表示该函数是一个函数。你可以从概念上思考这个问题:“所有多边形都有一个面积,所以我应该可以问它是什么,但是除非多边形有一个特定的类型(正方形、圆形),否则它不会知道它的面积是什么”


    这意味着多边形类是一个抽象类。通过不在矩形类中定义
    getArea()
    ,矩形类也是一个抽象类。您无法实例化矩形,因为编译器不知道任何
    Rectangle::getArea()
    函数定义。

    如前所述,printDetails的行为将不符合预期。

    我还认为,仅仅在Rectangle类中声明getArea()有点作弊,因为您没有为它提供实现,如果您碰巧在代码中调用它,您将得到一个链接器错误。

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

  • 使用初始值设定项列表来指定值

  • 调用基类构造函数来设置颜色

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

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

  • 如果您确实想使用字符串作为颜色,请通过const引用传递它(并可能测试边缘情况,如空字符串)

  • printDetails
    可能应该是虚拟的,因此可以使用基类指针调用它。当前实现的行为可能不符合预期

  • 这个类似乎是为多态性而设计的。如果需要从基类指针删除,则必须定义虚拟析构函数。既然已经有了一个虚拟方法,它可能也不会有什么坏处

  • getArea
    printDetails
    应该声明为const,以便可以在const对象上调用它们。他们不应该修改对象

  • 这只是一个可能性列表。许多
    Rectangle::Rectangle(string const & col, int len, int br) 
        : Polygon(col), length(len), breadth(br) {};
    
    Rectangle::Rectangle(string col, int len, int br)
    {
        length =len;
        breadth=br;
        setColour(col);
    }