继承和友元函数,从基类访问受保护的成员

Inheritance and friend functions, accessing protected members from base class

本文关键字:访问 受保护 成员 基类 友元 函数 继承      更新时间:2023-10-16

假设我有一个很大的类子,有很多成员和功能。为了处理大量数据,我决定创建类 PotentialCirlce (只有 3 个成员 - x, y, r(,基于PotentialCirlce进行大部分预处理,并在最后阶段创建对象Circle

a( 正确的方法吗?它是否会影响性能,或者更确切地说,我应该只使用Circle

在我看来,我可以使用继承:

class potentialCircle {
protected:
point_t center;
unsigned int radius;
public:
potentialCircle(int a, int b, unsigned int r) : center{ point_t(a,b) }, radius{ r } {}
potentialCircle() = delete;
potentialCircle(const potentialCircle&) = default;
potentialCircle(potentialCircle&&) = default;
potentialCircle& operator=(const potentialCircle&) = default;
potentialCircle& operator=(potentialCircle&&) = default;
virtual ~potentialCircle() = default;
};
class Circle : public potentialCircle {
// members detected based on Hough Circle Transform
//point_t center;                           // coordinates of center point
point_t alternative_center;                 // needed when center is out of frame
//unsigned int radius;                      // radius
// members calculated based on Flood Fill algorithm (more realistic)
unsigned int area = 0;
float diameter = 0;
float perimeter = 0;
....
};

b( 我应该把需要比较两个不同对象的方法放在哪里?一个对象类型为圆,一个对象为潜在卷轴? 目前,我将以下函数定义为 Circle 的一部分

bool Circle::is_greater(const std::pair<potentialCircle, int>& point_pair) const;

但我无法访问 potentialCircle 的受保护数据成员,尽管 Circle 是从 potentialCircle 继承的。 也许我应该将is_greater((定义为namepsace的一部分,并使其成为Circle和potentialCircle的朋友。

你有更好的主意吗?

没有一种很好的方法来比较不同类型的对象,因为它在实践中几乎没有意义。这种比较的目的是什么。

现在,即使您有一个类,如果排序不是类型不瞬变的,最好使用外部类进行排序。

class CircleDiameterLess
{
public:
bool operator()(const Circle &lhs, const Circle &rhs)
{
return lhs.diameter < rhs.diameter;
}
};

这样,您可以有多种方式对数据进行排序,并且与 STL 配合得很好。

代码的另一个问题是,如果类circle

具有派生自具有半径的类potentialCirclediameter是没有意义的。您的代码将难以维护,因为它很难理解。

您希望存储直径或半径并计算另一个。

unsigned int get_diameter() const { return radius * 2; }

alternative_center这样的成员毫无意义。一个圆只有一个中心。如果你的班级不尊重基本期望,这将使代码难以维护,因为没有人会知道一个圆在 3 个月内有 2 个中心,包括你!

在像您这样的情况下,添加公共访问器是有意义的。

class potentialCircle
{
public:
unsigned int get_radius() const { return radius; }
....
};

这样,您仍然可以将数据设为私有(或有时受到保护(,同时对数据具有只读访问权限。这样,您可以根据需要编写比较函数。在实践中,如果你有一个表示圆的类,你通常希望至少能够通过函数的方式获得基本属性,如半径、面积、边界矩形。

另一件事是,公共派生作为你的(来自potentialCircle(只有在你有其他类派生自它时才有意义。但是,如果是这种情况,那么您将如何比较其他类型的圆圈?

笔记:

  • 对于C++ 20,三向比较会更好。