【发布时间】:2015-12-03 23:05:59
【问题描述】:
我想了解何时应该使用引用或指针。
让我们以 Polygon 类为例,它使用 Rectangle 类作为其内部边界框。
多边形.h
class Polygon {
private:
std::list<Point> _points;
Rectangle _boundingBox;
public:
Polygon(const std::list<Point> &);
public:
const std::list<Point> &getPoints() const;
const Rectangle &getBoundingBox() const;
private:
void setBoundingBox();
};
多边形.cpp
#include <iostream>
#include "Polygon.h"
Polygon::Polygon(const std::list<Point> &points)
{
if (points.size() < polygon::MIN_SIDE + 1) {
throw std::invalid_argument("A polygon is composed of at least 3 sides.");
}
if (points.front() != points.back()) {
throw std::invalid_argument("A polygon must be closed therefore the first point must be equal to the last one.");
}
std::list<Point>::const_iterator it;
for (it = ++points.begin(); it != points.end(); ++it) {
this->_points.push_back(*it);
}
this->setBoundingBox();
}
void Polygon::translate(const std::array<float, 2> &vector)
{
std::list<Point>::iterator it;
for (it = this->_points.begin(); it != this->_points.end(); ++it) {
(*it).setX((*it).getX() + vector[0]);
(*it).setY((*it).getY() + vector[1]);
}
Point topLeft = this->_boundingBox->getTopLeft();
Point bottomRight = this->_boundingBox->getBottomRight();
topLeft.setX(topLeft.getX() + vector[0]);
topLeft.setY(topLeft.getY() + vector[1]);
bottomRight.setX(bottomRight.getX() + vector[0]);
bottomRight.setY(bottomRight.getY() + vector[1]);
}
const std::list<Point> &Polygon::getPoints() const
{
return this->_points;
}
const Rectangle &Polygon::getBoundingBox() const
{
return this->_boundingBox;
}
void Polygon::setBoundingBox()
{
float xMin = this->_points.front().getX();
float xMax = this->_points.front().getX();
float yMin = this->_points.front().getY();
float yMax = this->_points.front().getY();
std::list<Point>::const_iterator it;
for (it = this->_points.begin(); it != this->_points.end(); ++it)
{
Point point = *it;
if (point.getX() < xMin) {
xMin = point.getX();
}
if (point.getX() > xMax) {
xMax = point.getX();
}
if (point.getY() < yMin) {
yMin = point.getY();
}
if (point.getY() > yMax) {
yMax = point.getY();
}
}
this->_boundingBox = new Rectangle(Point(xMin, yMin), Point(xMax, yMax));
}
std::ostream &operator<<(std::ostream &out, const Polygon &polygon)
{
std::list<Point>::const_iterator it;
for (it = polygon.getPoints().begin(); it != polygon.getPoints().end(); ++it) {
out << (*it);
if (it != polygon.getPoints().end()) {
out << " ";
}
}
return out;
}
矩形.h
#pragma once
#include <stdexcept>
#include "Point.h"
class Rectangle {
private:
Point _topLeft;
Point _bottomRight;
public:
Rectangle(const Point &, const Point &);
public:
const Point &getTopLeft() const;
const Point &getBottomRight() const;
float getWidth() const;
float getHeight() const;
};
矩形.cpp
#include "Rectangle.h"
Rectangle::Rectangle(const Point &topLeft, const Point &bottomRight)
{
if (topLeft.getX() > bottomRight.getX() || topLeft.getY() > bottomRight.getY()) {
throw std::invalid_argument("You must specify valid top-left/bottom-right points");
}
this->_topLeft = topLeft;
this->_bottomRight = bottomRight;
}
const Point &Rectangle::getTopLeft() const
{
return this->_topLeft;
}
const Point &Rectangle::getBottomRight() const
{
return this->_bottomRight;
}
float Rectangle::getWidth() const
{
return this->_bottomRight.getX() - this->_topLeft.getX();
}
float Rectangle::getHeight() const
{
return this->_bottomRight.getY() - this->_topLeft.getY();
}
点.h
#pragma once
#include <ostream>
#include <cmath>
class Point {
private:
float _x;
float _y;
public:
Point(float = 0, float = 0);
public:
float distance(const Point &);
public:
float getX() const;
float getY() const;
void setX(float);
void setY(float);
};
std::ostream &operator<<(std::ostream &, const Point &);
bool operator==(const Point &, const Point &);
bool operator!=(const Point &, const Point &);
Point.cpp
#include "Point.h"
Point::Point(float x, float y)
{
this->_x = x;
this->_y = y;
}
float Point::distance(const Point &other)
{
return std::sqrt(std::pow(this->_x - other.getX(), 2) + std::pow(this->_y - other.getY(), 2));
}
float Point::getX() const
{
return this->_x;
}
float Point::getY() const
{
return this->_y;
}
void Point::setX(float x)
{
this->_x = x;
}
void Point::setY(float y)
{
this->_y = y;
}
std::ostream &operator<<(std::ostream &out, const Point &point)
{
out << "(" << point.getX() << ", " << point.getY() << ")";
return out;
}
bool operator==(const Point &p1, const Point &p2)
{
return p1.getX() == p2.getX() && p1.getY() == p2.getY();
}
bool operator!=(const Point &p1, const Point &p2)
{
return p1.getX() != p2.getX() || p1.getY() != p2.getY();
}
这个sn-p代码带来了很多问题。
- 这不会编译,因为很明显,每当我们尝试创建 Polygon 时,它最终都会尝试使用不存在的默认构造函数创建 Rectangle。
- 我不能使用初始化列表,因为显然边界框取决于我的点列表中的一些计算值。
- 我可以创建一个默认构造函数,默认为 Rectangle 创建两个 Point(0, 0),但这没有多大意义。
- 我可以使用指针,但我觉得这不是最好的解决方案,因为我倾向于认为这主要用于 C++ 中的多态性,我们应该尽可能选择引用。
我应该如何继续?
我觉得我错过了关于 C++ 的一些东西,并且可以从中学到很多东西。
【问题讨论】:
-
在这种情况下,您不应使用引用或指针,而应使用实际对象。这就是您在标题中声明的内容,因此您需要做的就是在问题发生时解决它们。为
Rectangle创建一个默认构造函数,或将其分配给构造函数中的默认(空)矩形。 -
也向我们展示
Rectangle类。 -
我不是专家,我理解默认参数的概念以及应该如何使用它们,对我来说,不传递任何东西就创建一个 Rectangle 似乎是不对的,我的意思是什么是真正的语义默认矩形?我添加了 Rectangle 类。
-
Rectangle *Polygon::getBoundingBox() const不匹配,*应该是&。尽管我会考虑为此(以及您的大多数吸气剂)按价值返回。通过引用返回是为了性能而牺牲简单性的尝试,但是对于小对象,并不总是清楚这是性能提升还是性能损失。一方面,你失去了复制省略。 -
@M.M 我修复了这个小错误(主要是因为我在过去几个小时内尝试了不同的东西,每当我在这里发帖时我都忘记了这个)我现在是一名学生,我不能通过课程出于纯粹的评分原因,这就是为什么在我的代码中所有内容都始终是通过引用的原因。我不知道所有性能原因,但问题主要在于指针/引用和默认构造函数之间是否存在。以及解决方法。
标签: c++ pointers reference initializer-list