如何设置表示接口的类?这只是一个抽象基类吗?
当前回答
您还可以考虑使用NVI(非虚拟接口模式)实现的合约类。例如:
struct Contract1 : boost::noncopyable
{
virtual ~Contract1() = default;
void f(Parameters p) {
assert(checkFPreconditions(p)&&"Contract1::f, pre-condition failure");
// + class invariants.
do_f(p);
// Check post-conditions + class invariants.
}
private:
virtual void do_f(Parameters p) = 0;
};
...
class Concrete : public Contract1, public Contract2
{
private:
void do_f(Parameters p) override; // From contract 1.
void do_g(Parameters p) override; // From contract 2.
};
其他回答
我还是C++开发的新手。我从Visual Studio(VS)开始。
然而,似乎没有人提到VS(.NET)中的__interface。我不太确定这是否是声明接口的好方法。但它似乎提供了额外的强制执行(文件中提到)。这样就不必显式指定虚拟TYPE Method()=0;,因为它将被自动转换。
__interface IMyInterface {
HRESULT CommitX();
HRESULT get_X(BSTR* pbstrName);
};
然而,我不使用它,因为我担心跨平台编译兼容性,因为它只在.NET下可用。
如果有人对此感兴趣,请分享。:-)
谢谢
我的答案与其他人基本相同,但我认为还有两件重要的事情要做:
如果有人试图删除IDemo类型的对象,请在接口中声明一个虚拟析构函数或创建一个受保护的非虚拟析构器,以避免未定义的行为。使用虚拟继承来避免多重继承的问题。(当我们使用接口时,通常会有多重继承。)
和其他答案一样:
使用纯虚拟方法创建类。通过创建另一个重写这些虚拟方法的类来使用该接口。类IDemo{公众:虚空OverrideMe()=0;virtual~IDemo(){}}或类IDemo{公众:虚空OverrideMe()=0;受保护的:~IDemo(){}}和class Child:虚拟公共IDemo{公众:虚拟空OverrideMe(){//做一些事情}}
C++中没有“接口”本身的概念。AFAIK,接口首先在Java中引入,以解决缺少多重继承的问题。事实证明,这个概念非常有用,在C++中使用抽象基类也可以达到同样的效果。
抽象基类是一个类,其中至少一个成员函数(Java语言中的方法)是使用以下语法声明的纯虚拟函数:
class A
{
virtual void foo() = 0;
};
抽象基类不能实例化,即不能声明类A的对象。只能从A派生类,但任何不提供foo()实现的派生类也将是抽象的。为了停止抽象,派生类必须为其继承的所有纯虚拟函数提供实现。
请注意,抽象基类可以不仅仅是一个接口,因为它可以包含非纯虚拟的数据成员和成员函数。接口的等价物是一个抽象基类,没有任何数据成员,只包含纯虚拟函数。
而且,正如MarkRansom所指出的,抽象基类应该像任何基类一样提供虚拟析构函数。
考虑这一点的一个好方法是继承接口而不是继承实现。在C++中,您可以同时继承接口和实现(公共继承),也可以只继承实现(私有继承)。在Java中,您可以选择只继承接口,而不继承实现。
除了上面写的内容,还有一点补充:
首先,确保析构函数也是纯虚拟的
第二,您可能希望在执行时实际上继承(而不是正常继承),只是为了获得好的度量。
为了扩展bradtgmurray的答案,您可能希望通过添加虚拟析构函数来对接口的纯虚拟方法列表进行一个例外。这允许您将指针所有权传递给另一方,而不暴露具体的派生类。析构函数不必做任何事情,因为接口没有任何具体的成员。将函数定义为虚拟函数和内联函数可能看起来很矛盾,但相信我,事实并非如此。
class IDemo
{
public:
virtual ~IDemo() {}
virtual void OverrideMe() = 0;
};
class Parent
{
public:
virtual ~Parent();
};
class Child : public Parent, public IDemo
{
public:
virtual void OverrideMe()
{
//do stuff
}
};
您不必为虚拟析构函数包含一个主体——事实证明,某些编译器在优化空析构函数时遇到了问题,最好使用默认值。
推荐文章
- 为什么我的程序不能在Windows 7下用法语编译?
- 如何获取变量的类型?
- 什么是奇怪的重复模板模式(CRTP)?
- 连接两个向量的最佳方法是什么?
- 在c++中,是通过值传递更好,还是通过引用到const传递更好?
- 在STL中deque到底是什么?
- Windows上最好的免费c++分析器是什么?
- 如何自动转换强类型枚举为int?
- 在一个类中使用具有成员函数的泛型std::function对象
- 'for'循环中的后增量和前增量产生相同的输出
- 虚函数和纯虚函数的区别
- 转换List<DerivedClass>到List<BaseClass>
- c++中的_tmain()和main()有什么区别?
- 内存泄漏是否正常?
- 当启用c++ 11时,std::vector性能回归