用C ++扩展库

时间:2012-06-26 05:39:52

标签: c++ inheritance

是否可以在没有源代码的情况下从C ++库扩展类?标题是否足以允许您使用继承?我正在学习C ++并且正在进入理论。我会测试这个,但我不知道如何。

4 个答案:

答案 0 :(得分:7)

简短回答 是的,最终你可以。

答案很长警告:以下文字可能会伤害儿童敏感的OOP整体主义者。如果你觉得或保持成为其中之一,请远离这个答案:我的和你的每个人生活将会更加轻松

让我揭开一个秘密:STL代码只不过是带有头文件和库的常规C ++代码,就像你的代码可以 - 而且很可能 - 那样。 STL的作者只是程序员,就像你一样。它们在编译器方面并不特别。他没有任何超级大国。他们像你一样坐在他们的厕所上,做你正在做的事情。不要过分误解他们。

STL代码遵循与您自己编写的代码完全相同的规则:被覆盖的内容将被调用而不是基础:总是如果它是虚拟的,并且仅根据其引用指针的静态类型(如果它不是虚拟的话),像所有其他C ++代码一样。不多也不少。

重要的是不要破坏关于STL名称约定和语义的设计问题,以便每次进一步使用代码都不会混淆人们的期望,包括你自己,10年后阅读代码,不记得某些决定。

例如,覆盖std::exception::what()必须返回一个解释性持久性C字符串,(如STL文档所述)并且不会添加意外的其他模糊操作。

此外,重写流或流媒体操作符应该完成整个设计(你真的需要覆盖或只是 streambuffer 或只是添加一个特定的< em> facet 到 locale 它是什么?):换句话说,不仅要研究“类”,还要研究它所有“世界”的设计,以正确理解它是如何工作的在附近。

最后,但并非最不重要的是,最具争议的方面之一是容器和一切没有虚拟析构函数。

我的观点是关于“经典OOP规则:不要导出没有虚拟析构函数”的噪音过度膨胀:根本不要指望cow成为horse只是因为您在其上放置了saddle

如果你需要(真的真的需要)一个用std :: string完全相同的接口管理一个字符序列的类,它能够隐式转换为std :: string并且有更多东西,你有两个方法:

  • 做好女孩做的事情,嵌入std:string并重写所有112(是的:他们超过100)的方法,除了调用它们之外什么都不做,并确保你仍然处女与另一个好男孩程序员的代码结婚,或者......
  • 发现这需要大约30年,你冒着成为40岁的风险。处女没有好的好男孩程序员对此感兴趣,更实际,牺牲你的童贞并衍生std::string。你唯一要放弃的是你与一个完整主义者结婚的可能性。你甚至可以发现它不一定是个问题:你甚至远离被他杀死的风险!

你必须要特别注意的是,由于std::string不是多态的,你的推导就会如此,所以不要指望std::string*std::string&引用{ {1}}调用你的方法,包括析构函数,这对所有其他方法都没有特别的尊重;它只是遵循完全相同的规则。 但是......嘿,如果你嵌入并编写了一个隐式转换运算符,你将得到完全相同的结果,不能再少了!

规则很简单:不要让自己成为虚拟的析构函数,也不要假装“OOP替换原则”来处理不是为OOP设计的东西,一切都会正确。

所有OOP完整主义 requemscant in pacem 他们的永恒睡眠,你的代码将工作,而他们仍然重写100+ std :: string方法只是为了嵌入它。

答案 1 :(得分:4)

是的,该课程的宣言足以从中获得。

当您链接到库时,其余代码将会被选中。

答案 2 :(得分:2)

是的,您可以在标准C ++库中扩展类。头文件就足够了。

一些例子:

  • 扩展std::exception类以创建自定义异常
  • 扩展流库以在您的应用程序中创建自定义流

但是你要注意的一件事是不要扩展没有virtual destructor的类。示例包括std::vectorstd::string

编辑:我刚刚发现了关于此主题的另一个问题Extending the C++ Standard Library by inheritance?

答案 3 :(得分:1)

只有一个头文件足以从该类继承。
C ++程序分两个阶段构建:

  • 编译
    编译器查找类型的定义并检查程序的语言正确性。这会生成目标文件。
  • 链接
    编译的目标文件链接在一起形成可执行文件。

只要你有头文件(编译)和库(链接),你就可以从一个类中派生出来。
但是请注意,必须要注意该类是否确实用于继承 例如:如果你有一个非virtual析构函数的类,那么该类不适用于继承。就像所有标准库容器类一样。

简而言之,只要拥有类的接口就足以进行派生,但类的实现和设计语义确实起着重要的作用。