是否可以在没有源代码的情况下从C ++库扩展类?标题是否足以允许您使用继承?我正在学习C ++并且正在进入理论。我会测试这个,但我不知道如何。
答案 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)的方法,除了调用它们之外什么都不做,并确保你仍然处女与另一个好男孩程序员的代码结婚,或者...... 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::vector
,std::string
编辑:我刚刚发现了关于此主题的另一个问题Extending the C++ Standard Library by inheritance?
答案 3 :(得分:1)
只有一个头文件足以从该类继承。
C ++程序分两个阶段构建:
只要你有头文件(编译)和库(链接),你就可以从一个类中派生出来。
但是请注意,必须要注意该类是否确实用于继承
例如:如果你有一个非virtual
析构函数的类,那么该类不适用于继承。就像所有标准库容器类一样。
简而言之,只要拥有类的接口就足以进行派生,但类的实现和设计语义确实起着重要的作用。