C中的继承:如何将“超类”属性隐藏到扩展它的类

Posted

技术标签:

【中文标题】C中的继承:如何将“超类”属性隐藏到扩展它的类【英文标题】:Inheritance in C: how to hide "super class" attributes to the class extending it 【发布时间】:2020-05-28 09:00:24 【问题描述】:

作为一种学习体验,我尝试在 C 中实现简单的类继承,以及其他 OOP 特性。

到目前为止,我已经能够从外部上下文中正确地隐藏类的“私有”函数和属性。

让我们将 Point 视为一个简单的类示例。它由三个模块组成:

public.h

#ifndef POINT_PUBLIC_H_
#define POINT_PUBLIC_H_

typedef struct Point Point;

Point* newPoint(const int x, const int y);

int getX(const Point* self);

int getY(const Point* self);

void setX(Point* self, const int x);

void setY(Point* self, const int y);

void printPoint(const Point* self);

#endif

这基本上是 Point 的公共接口,它还定义了 Point 类型,引用在另一个模块中声明的结构,隐藏其属性。

受保护的.h

#ifndef POINT_PROTECTED_H_
#define POINT_PROTECTED_H_

struct Point 

    int x;
    int y;
;

#endif

它承载实际的结构定义,还可以包含只能通过继承类访问的​​函数原型。

然后是 implementation.c,它包括 public.h 和 protected.h,并包含公共、保护和私有函数的实际代码。

这很好用,但如果我想定义一个扩展 Point 的 Circle 类怎么办?

我设想过这样的事情:

#ifndef CIRCLE_PROTECTED_H_
#define CIRCLE_PROTECTED_H_

#include "../Point/protected.h"

struct Circle 

    Point parent;
    int radius;
;

#endif

由于 Point 的公共函数需要一个指向 Point 的指针,并且由于 Circle 结构的第一个属性是一个 Point(不是指向它的指针),给定一个 Circle* c 对象,就可以执行类似 @ 的操作987654326@。 虽然这很好用,但我不满意的是我可以直接访问 Circle 模块中的 Point 对象(当然包括 Circle 结构中的那个)的属性。 将结构定义移动到实现模块将使其属性完全私有,但我将无法直接实例化 Point 对象以设置继承机制。 有没有办法让继承工作,同时维护正在扩展的类的隐私?

【问题讨论】:

在 C 中编程时可以使用 OOP 概念,但这是您达到极限的地方。对于这些细节,您应该使用真正的 OO 语言。 我知道。我不一定要这样做,因为我打算在实际程序中使用这些概念。正如我所说,这只是一个学习新东西的实验。当然,如果我的要求真的无法完成,我可以接受。但是,如果有人知道一种不同的、更有效的方法,我很想了解它:) 您可能会使用(足够大的)字符缓冲区实例化 Point 的不透明版本,传递它并将其转换为函数/源文件中的真实 Point 结构,这可能知道定义.但我永远不会在生产代码中这样做;) 相关:***.com/questions/351733/… 我不认为从Circle 中隐藏Point 是一个好主意(在C 中)。您有一个图形源集,然后是用户代码。图形代码应该知道所有形状和操作的实现;用户代码可以使用 void 指针。 【参考方案1】:

感谢@RobertS 对 Monica Cellio 的支持,我浏览了您链接的主题一会儿,它实际上给了我一个想法。

我试图将结构实际拆分为两部分,一个是受保护的部分,它意味着对继承类可见,另一个是在 implementation.c 模块之外完全不可见的私有部分。

这是我所做的:在 implementation.c 中我定义了一个包含所有私有属性的新结构:

struct hiddenPoint 

    int x;
    int y;
;

在 protected.h 中,我定义了一个引用这个新结构的类型,并在实际的 Point 结构中放置了一个指向它的指针

typedef struct hiddenPoint hiddenPoint;

struct Point 

    int aCircleCanSeeThis;
    hiddenPoint* hidden;
;

由于 hidden 是一个不透明的指针,即使 struct Point 是可见的,它的一些属性仍然可以被设置为不可访问。这个结构当然也可以托管受保护的属性,如图所示。

这就是我的 Circle 结构:

struct Circle 

    Point parent;
    hiddenCircle* hidden;
;

它似乎工作。当然,它使事情变得有点复杂(现在它是 p->hidden->x,而不仅仅是 p->x),但它可以满足我的要求。不知道有没有好的解决方法,请告诉我!另外,如果还有其他方法,我仍然想听听这些方法:)

【讨论】:

以上是关于C中的继承:如何将“超类”属性隐藏到扩展它的类的主要内容,如果未能解决你的问题,请参考以下文章

OO面向对象———扩展类与被扩展类

如何在不修改继承类(基类)的情况下隐藏类中的继承属性?

Java核心技术-继承

OOP:如何动态扩展超类中的函数

Django 模型继承和外键

19.面向对象(继承)