假设我有通常的class Animal
抽象类和class Dog : public Animal
class Cat : public Animal
,它使它成为一个具体类,你可以实例化一个对象。进一步假设您有一个函数foo(Animal a)
,将猫或狗作为对象。 C ++过去常常编译为C语言,并构建一个vTable
来维护那里的对象。
但是我的一个学生问我这个问题:在这些概念是程序员之间的常见谈话之前,他们是如何在他们的C日常编码中实际做的?什么是(是?)在C中编程这些概念的惯用方法?
我已经筛选了linux内核和其他OSS项目,但我还没有找到一个清晰的模式:有时它的工会(针对不同的结构),有时它&# 39; s函数指针等,但我希望得到行业知识渊博的人的直接答案,他们已经完成并且对C有很多经验。
用一句话来说:什么是惯用C继承和多态?
答案 0 :(得分:7)
简单程序,例如为学校作业编写的程序,使用由联合和可选的枚举作为类型鉴别器的结构实现多态。然后,每个“方法”都包含一个switch语句,该语句调用适合该子类型的函数。显然,这不会扩展到需要能够在不改变基类定义的情况下添加子类的更多系统。
多态性本身很容易用接收显式self
参数的函数指针表示。开放式继承可以通过嵌入其超类的“继承”结构来实现:
struct base {
// ... members here ...
};
struct inherited {
struct base base;
// ... inherited members here ...
};
指向struct inherited
的指针可以安全地转换为struct base *
,这是C标准明确祝福的做法。这些强制转换通常隐藏在宏之后,甚至可能在可能的情况下执行运行时类型检查。
实现这一点非常笨拙,因为没有模板,没有自动调用析构函数,没有例外,也没有STL。换句话说,程序员必须小心处理错误处理和析构函数调用,并且类型方差必须通过运行时的回调处理(考虑std::sort()
和qsort()
之间的差异)或者难以处理维护预处理器技巧。
尽管存在困难,但在C中实现C ++功能的有意义的子集肯定是可能的,甚至可以在过程中实现C的简单性。要研究这种方法在生产级别上的实际示例,请查看CPython解释器的实现,或GTK +使用的glib对象系统。
答案 1 :(得分:0)
我看到了使用#defines
在源代码和包含文件中创建抽象名称的代码。例如,可以重复使用相同的例程来处理字节short
,int
s,float
和double
s。代码很乱,很难理解。
答案 2 :(得分:-1)
在面向对象编程的优势之前,应用程序使用过程代码,其中功能被“封装”在函数层次结构中,层次结构顶部的函数与抽象一起工作,并且随着我们的进展变得越来越具体和详细在层次结构中。某些API提供了创建只能通过句柄操作的结构的方法。示例:在C中,文件句柄隐藏了处理文件的详细信息。
至于在C中做OO,我相信如果没有适当的语言支持和合适的结构,它永远不是一个可行的选择。你得到的东西不值得用函数指针伪装OO所涉及的痛苦。