继承和友元函数,从基类访问受保护的成员
Posted
技术标签:
【中文标题】继承和友元函数,从基类访问受保护的成员【英文标题】:Inheritance and friend functions, accessing protected members from base class 【发布时间】:2020-07-03 00:44:09 【问题描述】:假设我有一个大类Circle,它有很多成员和函数。为了处理大量数据,我决定创建类 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 类型的对象和一个 PotentialCircle? 目前,我已将以下函数定义为 Circle 的一部分
bool Circle::is_greater(const std::pair<potentialCircle, int>& point_pair) const;
但我无权访问 potentialCircle 的受保护数据成员,尽管 Circle 是从 potentialCircle 继承的。 也许我应该将 is_greater() 定义为 namepsace 的一部分,并使其成为 Circle 和 potentialCircle 的朋友。
你有更好的主意吗?
【问题讨论】:
记住Circle“是一个”潜在的Circle。 (圈子:公共潜力圈子)。如果potentialCircle的所有子类都有is_greater,或许它可能是基类中的一个虚函数,当基类函数不够用时被派生类覆盖。 【参考方案1】:实际上并没有什么好的方法来比较不同类型的对象,因为它在实践中几乎没有意义。这种比较的目的是什么。
现在,即使你有一个类,如果排序不是类型的内在因素,最好使用外部类进行排序。
class CircleDiameterLess
public:
bool operator()(const Circle &lhs, const Circle &rhs)
return lhs.diameter < rhs.diameter;
;
这样,您可以有多种方式对数据进行排序,并且与 STL 配合得很好。
您的代码的另一个问题是,如果有一个类circle
和一个派生自具有半径的类potentialCircle
的diameter
几乎没有意义。您的代码将难以维护,因为它难以理解。
您想存储直径或半径并计算另一个。
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,三路比较会更好。【讨论】:
以上是关于继承和友元函数,从基类访问受保护的成员的主要内容,如果未能解决你的问题,请参考以下文章