C++ 的问题构造函数

发布于 2024-11-06 04:24:59 字数 1356 浏览 1 评论 0原文

编辑:这个问题出现了,我想我答对了!去堆栈溢出吧!! :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 color; 是私有的,但 setColour 是公共的,所以我无法弄清楚。除非它的 Rectangle::Rectangle(string col, int len, int br):length(len), breadth(br) 然后在构造函数内设置颜色或其他东西。

它只值 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();
}

EDIT: This question came up and I think I aced it! Go StackOverflow!! :D

I have exams coming up, and one of the questions on last year's exams was to spot the problem with implementation of the following constructor and to write a corrected one.

Rectangle::Rectangle(string col, int len, int br)
{
    setColour(col);
    length =len;
    breadth=br;
}

The class definitions are as follows:

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;
};

I've written the code into the compiler and it runs fine. I'm guessing the question is relating to inheritance, since string colour; is private, but setColour is public so I cant figure it out. Unless its Rectangle::Rectangle(string col, int len, int br):length(len), breadth(br) and then set the colour inside the construcor or something.

Its only worth 3 marks so its not that big a deal if nobody wants to answer, but I figure if I'm going to have a career as a programmer, its in my interest to know as much as possible. ;)

Thanks for any help.

PS, see getArea() in Rectangle. When I remove that it tells me it "cannot instantiate the abstract class". What does that mean?

EDIT: Here's the main:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

莳間冲淡了誓言ζ 2024-11-13 04:24:59

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

Rectangle::Rectangle(string col, int len, int br) 
: Polygon(col), length(len), breadth(br)
{

}

请注意,初始化列表也可以调用 Polygon 的构造函数。

请参阅为什么我应该更喜欢使用成员初始化列表? 有关使用初始化列表优点的完整说明。

I don't see anything wrong, though you could make it more efficient by using an initialization list (otherwise your private members of both classes get initialized twice):

Rectangle::Rectangle(string col, int len, int br) 
: Polygon(col), length(len), breadth(br)
{

}

Notice that the initialization list can call the constructor of Polygon as well.

See Why should I prefer to use member initialization list? for a complete description of the advantages of using initialization lists.

橘亓 2024-11-13 04:24:59

如果是关于最佳 C++ 实践,那么:

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

If it's about best C++ practices, then:

  1. Pass string parameters by const reference;
  2. Use initializer list and initialize colour by passing it to parent constructor, not setColour.
少女的英雄梦 2024-11-13 04:24:59

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

The only thing I see off the bat is there is two printDetails() but the base class one is not virtual so you would not get the polymorphic behavior expected.

梦年海沫深 2024-11-13 04:24:59

我看到的主要“问题”(有点小)是派生构造函数让父类使用其默认的 colo(u)r 值(“红色”),然后提供自己的值。这有点浪费,因为你本可以从一开始就给它正确的。

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) {};

对于每个调用的 Rectangle 构造函数,此公式将 4 个 std::string 构造(和 3 个销毁)减少到 2 个。它可以通过对 Polygon 构造函数进行相同的更改,可以进一步简化为 1。

The main "issue" I see (and it is kinda minor) is that the derived constructor lets the parent class use its default colo(u)r value ("red"), and then supplies its own. That's kinda wasteful, when you could have given it the correct one from the get-go.

Rectangle::Rectangle(string col, int len, int br) : Polygon(col) {
    length =len;
    breadth=br;
};

Now, having done the above, you might as well intialize all the members that way:

Rectangle::Rectangle(string col, int len, int br) 
    : Polygon(col), length(len), breadth(br) {};

Hmmm. Now that I look at this, there's another thing wrong with it. Your constructors are passing in std::string objects by copy, and not modifying them. That's a waste too. All the constructor string parameters ought to be changed to string const & parameters. This potentially avoids an extra copy construction of a string at runtime, and notifies the compiler and the users that you aren't actually modifying the input strings (which is good practice when you in fact aren't).

So the final version would look more like:

Rectangle::Rectangle(string const & col, int len, int br) 
    : Polygon(col), length(len), breadth(br) {};

This formulation takes you from 4 std::string constructions (and 3 destructions) for every Rectangle constructor called down to 2. It can be further taken down to one by making the same change to the Polygon constructor.

鹤舞 2024-11-13 04:24:59

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

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

关于 getArea()
当您删除它时它无法编译的原因是因为该函数被标记为 纯虚拟 在 Polygon 类中 virtual double getArea()=0; 使用 =0;

You should call the base constructor with the col parameter:

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

Concerning the getArea():
The reason it doesn't compile when you remove it is because that function is marked as pure virtual in your Polygon class virtual double getArea()=0; using the =0;

你的心境我的脸 2024-11-13 04:24:59

对于您关于 Rectangle::getArea() 的 PS:virtual double getArea()=0; 在 Polygon 中的声明意味着该函数是一个 纯虚函数。您可以从概念上思考这一点:“所有多边形都有一个面积,所以我应该能够询问它是什么,但除非多边形具有特定类型(正方形、圆形),否则它不会知道它的面积是什么”。

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

For your PS regarding Rectangle::getArea(): the declaration in Polygon of virtual double getArea()=0; means that the function is a pure virtual function. You can think of this conceptually: "All polygons have an area, so I should be able to ask what it is, but unless the polygon has a particular type (square, circle), it won't know what its area is".

What this means is that your Polygon class is an abstract class. By not defining getArea() in the Rectangle class, your rectangle class is also an abstract class. You can't instantiate a Rectangle because the compiler doesn't know about any Rectangle::getArea() function definition.

随波逐流 2024-11-13 04:24:59

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

Rectangle::Rectangle(string col, int len, int br)
    : Polygon(col), length(len), breadth(br)

它使用基类的构造函数,因此更简洁。

You can also add call to the base class constructor in your initializer list:

Rectangle::Rectangle(string col, int len, int br)
    : Polygon(col), length(len), breadth(br)

That uses the base class' constructor, so is a bit neater.

星軌x 2024-11-13 04:24:59

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

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

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

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

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

  5. 如果您确实想使用字符串作为颜色,请通过常量引用传递它(并且可能测试空字符串等边缘情况)。

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

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

  8. getAreaprintDetails 应声明为 const,以便可以在 const 对象上调用它们。它们不应修改对象。

这只是可能性的列表。其中许多取决于类的预期用途,可能不需要,但仔细考虑它们并没有什么坏处。

I can think of a number of possible problems here:

  1. Use initializer lists to assign the values.

  2. Call the base class constructor to set the color.

  3. A string might not be the best type to represent a color. Maybe an enum or a separate color class would be better here. This also prevents passing invalid colors, if properly done.

  4. Speaking of invalid values: length and breadth should be validated in the constructor (you don't want to end up with negative areas, do you?). At least use an assertion. It has no effect on release builds, but prevents development errors. For a more public interface, exceptions may also be an option (this is personal taste to some degree).

  5. If you really want to use a string for the color, pass it by const reference (and probably test for edge cases like the empty string).

  6. printDetails should probably be virtual, so you can call it with a base class pointer. The current implementation might not behave as intended.

  7. The class seems to be designed for polymorphism. A virtual destructor has to be defined, if deletion from a base class pointer is required. Since there already is a virtual method, it probably won't hurt either.

  8. getArea and printDetails should be declared const, so that they can be called on const objects. They shouldn't modify the object.

This is just a list of possibilities. Many of them depend on the intended usage of the class and might not be needed, but it doesn't hurt to consider them carefully.

一杆小烟枪 2024-11-13 04:24:59

如前所述,printDetails 不会按预期运行。
我还认为,仅在 Rectangle 类中声明 getArea() 有点作弊,因为您没有提供它的实现,如果您碰巧在代码中调用它,您会收到链接器错误。

As mentioned printDetails won't behave as expected.
I also think that just declaring getArea() within Rectangle class is kinda cheating because you do not provide implementation for it, and if you happen to call it within you code you would get a linker error.

枕花眠 2024-11-13 04:24:59

可能存在初始化顺序问题。 Polygon::setColour可以调用纯虚拟的Polygon::getArea。 (没有迹象表明需要这样做,但存在这种可能性。)矩形中的实现可能需要长度宽度来计算面积,但它们不是尚未初始化。

最小的修复方法是在调用 setColour 之前初始化长度宽度

Rectangle::Rectangle(string col, int len, int br)
{
    length =len;
    breadth=br;
    setColour(col);
}

当然,最好放弃纯虚拟getArea() 来自 Polygon 的声明,因为任何 Polygon 方法似乎都不需要它。但这超出了问题的范围。

An initialization order issue is possible. Polygon::setColour could call the pure virtual Polygon::getArea. (There is no indication that it would need to, but the possibility exists.) The implementation in Rectangle would presumably need length and breadth to compute the area, but they are not initialized yet.

The minimal fix is to initialize length and breadth before calling setColour:

Rectangle::Rectangle(string col, int len, int br)
{
    length =len;
    breadth=br;
    setColour(col);
}

It would be best, of course, to drop the pure virtual getArea() declaration from Polygon because it doesn't appear to be needed by any Polygon methods. But that is outside of the scope of the question.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文