[英]Unexpected output when dealing with operator overloading in C++ using
我正在嘗試通過“圓形”結構(基本上是二叉樹)來 go 。 每個圓都有一個 centerX、centerY、radius 和兩個葉節點。 這些葉子要么都是 null,要么都不是 null。 永遠不會有一個 null 和一個沒有 null。
我正在使用各種運算符重載函數。 我試圖用“,”運算符做一個,但實際上讓 function 命中時遇到了麻煩。
下面是相關代碼:
圈子.h:
#include <set>
#include <iostream>
using namespace std;
class Circle {
private:
double centerX, centerY, radius;
Circle* c1;
Circle* c2;
public:
static const int PAGE_DIMENSION = 200;
static const int DEFAULT_MAX_RADIUS = 15;
Circle( double x, double y, double radius, Circle* r1, Circle* r2 );
Circle( double x, double y, double radius );
Circle();
int isLeaf() const;
double getCenterX() const;
double getCenterY() const;
double area() const;
double getRadius() const;
Circle* getFirstSubcircle() const;
Circle* getSecondSubcircle() const;
bool operator<( Circle& other );
Circle* operator()( double x_in, double y_in);
Circle& operator=( Circle& rhs);
Circle* operator,( Circle& other );
double distance( Circle& rhs );
// THESE FUNCTIONS ARE NOT CLASS MEMBERS
// THEY ARE DEFINED OUTSIDE OF THE CLASS
// BUT REQUIRE ACCESS TO PRIVATE FIELDS
friend ostream& operator<<(ostream& osInput, Circle& circle);
friend ostream& operator/(ostream& osInput, Circle& circle);
friend Circle* reduce( set<Circle*>& circles);
};
圈子.cpp
#include <math.h>
#include <time.h>
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <set>
#include <fstream>
#include "circle.h"
using namespace std;
class CirclePair {
public:
Circle* c1;
Circle* c2;
double distance;
CirclePair(Circle* c1, Circle* c2, double distance)
{
this->c1 = c1;
this->c2 = c2;
this->distance = distance;
}
};
Circle::Circle( double x, double y, double radius, Circle* r1, Circle* r2 )
{
centerX = x;
centerY = y;
this->radius = radius;
c1 = r1;
c2 = r2;
}
Circle::Circle( double x, double y, double radius )
{
centerX = x;
centerY = y;
this->radius = radius;
c1 = NULL;
c2 = NULL;
}
Circle::Circle()
{
unsigned seed = time(0);
srand(seed);
int randomX = rand() % (PAGE_DIMENSION + 1);
int randomY = rand() % (PAGE_DIMENSION + 1);
int randomRadius = rand() % DEFAULT_MAX_RADIUS + 1;
centerX = randomX;
centerY = randomY;
radius = randomRadius;
}
int Circle::isLeaf() const
{
if (c1 == NULL && c2 == NULL) {
return 1;
}
return 0;
}
double Circle::getCenterX() const
{
return centerX;
}
double Circle::getCenterY() const
{
return centerY;
}
double Circle::area() const
{
double pi = 3.14159265358979323846;
return ( pi * (radius * radius));
}
double Circle::getRadius() const
{
return radius;
}
Circle* Circle::getFirstSubcircle() const
{
return c1;
}
Circle* Circle::getSecondSubcircle() const
{
return c2;
}
double Circle::distance( Circle& rhs )
{
double diffX = rhs.getCenterX() - getCenterX();
double diffY = rhs.getCenterY() - getCenterY();
return sqrt((diffX * diffX) + (diffY * diffY));
}
bool Circle::operator<( Circle& other )
{
cout << "Made it to operator <\n";
return area() < other.area();
}
Circle* Circle::operator()( double x_in, double y_in)
{
Circle* c = new Circle();
return c;
}
Circle& Circle::operator=( Circle& rhs)
{
cout << "Made it to operator =";
Circle* c = new Circle();
return *c;
}
Circle* Circle::operator,( Circle& other )
{
cout << "Made it to operator ,";
double distanceBetween = distance(other);
double c3Radius, c3CenterX, c3CenterY;
Circle* c3;
if (distanceBetween + getRadius() <= other.getRadius())
{
c3Radius = other.getRadius();
c3CenterX = other.getCenterX();
c3CenterY = other.getCenterY();
}
else
{
double theta = 0.5 + ((other.getRadius() - getRadius()) / (2 * distanceBetween));
c3Radius = (distanceBetween + getRadius() + other.getRadius()) / 2;
c3CenterX = ((1 - theta) * getCenterX() + theta * other.getCenterX());
c3CenterY = ((1 - theta) * getCenterY() + theta * other.getCenterY());
}
c3 = new Circle(c3CenterX, c3CenterY, c3Radius, this, &other);
return c3;
}
ostream& operator<<(ostream& osInput, Circle& circle)
{
osInput << "[ " << circle.centerX << ", " << circle.centerY << ", " << circle.radius << " ]\n";
return osInput;
}
ostream& operator/(ostream& osInput, Circle& circle)
{
if (circle.isLeaf()) {
osInput << " <circle cx=\"" << circle.centerX << "\" cy=\"" << circle.centerY <<"\" radius=\"" << circle.radius << "\" style=\"fill:blue;stroke:black;stroke-width:.05;fill-opacity:.1;stroke-opacity:.9\"/>\n";
}
else {
osInput << " <circle cx=\"" << circle.centerX << "\" cy=\"" << circle.centerY <<"\" radius=\"" << circle.radius << "\" style=\"fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5\"/>\n";
Circle* firstCircle = circle.getFirstSubcircle();
Circle* secondCircle = circle.getSecondSubcircle();
osInput / *firstCircle;
osInput / *secondCircle;
}
}
Circle* reduce( set<Circle*>& circles)
{
Circle* removeCirc1, removeCirc2;
//while (circles.size() != 1)
//{
std::set<Circle*>::iterator circlesIterator = circles.begin();
std::set<Circle*>::iterator circlesIterator2 = circles.begin();
std::set<CirclePair*> setOfCirclePairs = {};
while (circlesIterator != circles.end())
{
Circle *current = *circlesIterator;
while (circlesIterator2 != circles.end())
{
Circle *current2 = *circlesIterator2;
if (current != current2)
{
CirclePair *currentPair = new CirclePair(current, current2, current->distance(*current2));
setOfCirclePairs.insert(currentPair);
bool testBool = *current2 < *current;
cout << testBool << "\n";
Circle* newC = *current , *current2;
}
circlesIterator2++;
}
circlesIterator++;
}
CirclePair* minDistancePair = NULL;
std::set<CirclePair*>::iterator circlePairs = setOfCirclePairs.begin();
while (circlePairs != setOfCirclePairs.end()) {
CirclePair *currentCP = *circlePairs;
if (minDistancePair == NULL)
{
minDistancePair = currentCP;
}
else
{
if (currentCP->distance <= minDistancePair->distance)
{
minDistancePair = currentCP;
}
}
cout << currentCP->c1->getCenterX() << " " << currentCP->c2->getCenterX() << " " << currentCP->distance << "\n";
circlePairs++;
}
//find lowest distance pair
cout << minDistancePair->distance << "\n";
//}
}
測試.cpp:
#include <iostream>
#include <fstream>
#include <set>
#include <string>
#include <stdlib.h>
#include "circle.h"
using namespace std;
int main( int argc, char** argv ) {
Circle* circ = new Circle();
Circle* circ2_1 = new Circle(1, 2, 4);
Circle* circ2_2 = new Circle(134, 55, 3);
Circle* circ2 = new Circle(11, 21, 8, circ2_1, circ2_2);
Circle* circ3 = new Circle(145, 123, 8);
std::set<Circle*> setOfCircles { circ, circ2, circ3 };
Circle* completedCircle = reduce(setOfCircles);
}
在 tests.cpp 中調用的 reduce function 是應該為“,”操作激活代碼的地方。 function 在 circle.cpp 文件中稱為“Circle* reduce(set<Circle*>& circles)”。 在這個 function 中,以下代碼塊是對操作符函數進行一些調用的地方:
if (current != current2)
{
CirclePair *currentPair = new CirclePair(current, current2, current->distance(*current2));
setOfCirclePairs.insert(currentPair);
bool testBool = *current2 < *current;
cout << testBool << "\n";
Circle* newC = *current , *current2;
}
使用“<”返回的 testBool 正常工作並觸發“bool Circle::operator<( Circle& other )”function,但“newC”圓圈分配不起作用和“Circle* Circle::operator” ,( Circle& other )" function 永遠不會被調用。 這讓我感到困惑,因為我以同樣的方式稱呼它們。
關於如何正確調用“,”圓圈運算符的任何想法?
運算符,
優先級最低: https://en.cppreference.com/w/cpp/language/operator_precedence
由於 operator =
實際上具有更高的優先級,因此問題行的效果更接近於:
(Circle* newC = *current ), *current2;
但這不會觸發重載,因為左手現在是指針。
為了達到預期的效果,您可能需要在這對周圍放置大括號:
Circle* newC = ( *current , *current2);
Marc 的答案是正確的:但是我建議您應該尋找的解決方案是不要重載operator,
. 我還建議您不要為 class 重載operator<
或operator()
,並且不要為ostream
class 重載operator/
。
在編寫代碼時,您應該問自己的第一個問題是“我的代碼試圖做什么?” 過度使用運算符重載通常會混淆代碼背后的想法,除非非常謹慎地使用,例如即使您的operator<
function 它比較圓圈的面積也不會立即明顯。 operator()
也很混亂——我知道你可能還沒有實現它,但看起來你正准備制作一個 function 來構建一個新的圓圈; 對於閱讀它並且必須猜測Circle c(x,y,r)
和隨后的c(x1,y1)
之間的區別的任何人來說,這不會是直觀的。
ostream
class 的重載運算符是一個約定: <<
將事物“流”到 class 和>>
從 class 流事物。 嘗試閱讀具有ostream / object
的代碼將導致(幾乎)任何查看它的人都進行雙重檢查。
您已經遇到的另一個問題是運算符具有優先級,這可能會導致奇怪的效果。 通過 function 調用,您知道操作數不會神奇地消失在附近不同 function 的操作數中。
這不是對你個人的咆哮,我一直認為“如果我自己重載 XYZ 操作符會更好看”,因為我相信這里的很多人也有,但退后一步並意識到它實際上在編寫代碼時,讓其他人更難閱讀代碼非常重要——尤其是 C++,它還有許多其他有趣的方式讓我們絆倒。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.