我来自Java / python世界,很少或没有C ++经验,为了Liskov substitution principle和{{3的缘故,我习惯于使用接口来将类与实现之间的契约分开}}。
我不会讨论Java接口的所有优点,也不会介绍为什么引入接口(缺少多重继承)并且C ++不需要接口(dependency injection)。 我还发现了如何使用see here for example
我的问题更多是关于在C ++环境中这是否是一种好习惯。
据我了解,没有纯虚拟方法就不可能有等效的接口。这意味着将接口引入C ++将在代码中带来一些开销(因为虚拟方法equivalent of a Java interface in C++)。
因此,基于纯虚拟方法的接口是件好事吗?还有其他我不知道的实现Liskov替代原理和依赖注入的方法吗?也许使用模板?
例如,谷歌测试introduce an overhead,但提出了has it easy to mock virtual methods的方法。
我试图弄清楚我的编码习惯在新的C ++环境中是否仍然有用,或者我是否应该适应和更改范例。
[根据答案和评论进行编辑]
我得到了我一直在寻找的答案的一部分(即“是/否,带有参数”),我想我应该进一步阐明我仍在努力找出的问题
注释:
答案 0 :(得分:2)
我想说接口在C ++中仍然是一种好习惯。虚拟方法引入的开销很小,并且您会一次又一次听到,过早的优化是一个大错误。抽象基类是C ++中一个众所周知的,易于理解的概念,从长远来看,比卷积模板元编程更喜欢可读性,通用性的概念可以极大地帮助您。
话虽这么说,我会尽量避免多重继承。随之而来的是一些棘手的问题,这就是为什么Java明确禁止它进行常规继承的原因。一个简单的谷歌搜索可以给你更多的解释。
如果您有多个不相关的类,并且希望在每个类上调用相同名称的方法(例如foo()
),则可以使用一个模板化的函数来代替它,而不是使用接口
class A {
void foo() {
// do something
}
};
class B {
void foo() {
// do something
}
};
template <typename T>
void callFoo(const T& object) {
object.foo();
}
int main() {
A a;
B b;
callFoo(a);
callFoo(b);
return 0;
}
即使callFoo()
中没有明确的“合同”指出该类型必须支持.foo()
,但传递给它的任何对象也必须支持它,否则会出现编译错误。这是在编译时回避类型对象的常用方法,并且是某些情况下接口的替代方法。
最终,随着学习更多的C ++,您将使用自己的判断来决定如何实现所需的多态行为。怎么做都没有一个正确的答案,就像没有错误的答案一样。抽象基类和模板鸭子类型都是很好的工具,它们的用途略有不同。