【问题标题】:c++ "interface"-like classes similar to Java?类似于Java的c ++“接口”类?
【发布时间】:2011-11-20 05:51:46
【问题描述】:

在 Java 中,您可以将接口定义为没有实际代码实现的类,而只定义类必须实现的方法。这些类型可以作为参数传递给方法并从方法返回。据我所知,在 C++ 中,纯虚拟类不能用作参数或返回类型。有什么方法可以模仿 Java 的接口类?

我在 C++ 中有一个字符串类,以及从基本字符串类派生的不同编码(如 UTFxxx、ISOxxx 等)的几个子类。然而,由于有这么多不同的编码,基类没有有意义的实现。但是,如果我可以将它作为自己的对象来处理,并且对该对象的调用将调用它所继承的正确子类,它会很好地用作接口。

【问题讨论】:

  • 你当然可以使用抽象类作为参数或返回类型...你能显示一些代码吗?
  • 还没有实现纯虚拟基类。我正在阅读几篇讨论纯虚拟类可以做什么和不能做什么的文章。将它们用作参数的独立类型似乎不是其中之一。
  • 嗯,不是按值,但你当然可以通过指针或引用。
  • @NullUserExceptionఠ_ఠ 概念根本不像接口。接口在运行时运行并且关注多态性,而概念是编译时特性并且都是关于模板的。唯一真正的相似之处是他们使用代码指定了某种“契约”,这真的没什么特别的。
  • @MichaelPrice 那么,什么是更接近 C++ 中接口的概念?

标签: java c++ class interface


【解决方案1】:

如果您只使用引用或指针,则纯虚拟类可以用作返回类型。

其实在Java中,Interface foo = Implementer();等价于Interface* foo = Implementer();,而implements Foo就是public virtual Foo

这是一个 Java 示例:

interface Foo {
    public void doFoo();
}
class Bar implements Foo {
    public void doFoo() { }
}

它的 C++ 对应物:

struct Foo {
    virtual void doFoo() = 0;
    virtual ~Foo() { }
};
class Bar : public virtual Foo {
public:
    virtual void doFoo() { }
    virtual ~Bar() { }    
};

没错,如果你使用Foo foo;,C++ 会抱怨类型不完整。需要使用Foo& fooFoo* foosmart_pointer<Foo> foo

在此示例中,smart_pointer 可以是 scoped_ptrunique_ptrshared_ptr,具体取决于您是否愿意

  • 只需一个智能指针即可delete()s 销毁
  • 具有移动语义的智能指针
  • 进行引用计数的智能指针

请注意,如果您使用 boost 智能指针,请使用 get()/reset() 语义来获取和设置指针值。

【讨论】:

  • 你的意思是Interface * foo = new Implementer();
  • 没有。如果您立即查看左侧的 java sn-p,您可以假设 Implementer() 是一个返回 Interface 的函数,因此 Implementer 的类型为 Interface *()。我没有说明分配的含义——只说明了返回指针的事实。
  • 我明白了。很好。尽管我认为避免使用工厂方法会是一个更简单的示例。
【解决方案2】:

您不能按值使用纯虚类,但可以通过指针或引用传递它。这包括传递它的能力,包裹在智能指针类型中,例如 unique_ptrshared_ptr

您还应该确保在接口上使用virtual 关键字标记析构函数,以防止潜在的内存泄漏。

【讨论】:

  • 假设我创建了一个声明为纯虚拟类类型的对象,但实际上它是一个非纯虚拟的子类,我可以调用该对象并将其传递给方法吗?从方法返回它的类型?
  • 好吧,你不能创建纯虚类类型的对象……毕竟它是抽象的。 void func(Interface *); Interface * i = new Impl(); func(i); 完全有效。您也可以通过引用或指针返回接口。
  • Java在这方面与C++相同;你不能在 Java 中创建接口的实例,你只能通过引用传递它们。
【解决方案3】:

你当然可以像接口一样使用类,但它不是语言的构造,它只是一个只有纯虚方法的类。请记住,接口只是 Java 进行多重继承的方式,没有所有棘手的问题(祖父类的两个副本,具有相同名称的多个变量等)

【讨论】:

    【解决方案4】:

    这是 Google C++ 风格的接口定义:

    如果满足以下要求,则类是纯接口:

    • 它只有公共纯虚拟 ("= 0") 方法和静态方法(但请参阅下面的析构函数)。
    • 它可能没有非静态数据成员。
    • 它不需要定义任何构造函数。如果提供了构造函数,则它必须不带参数并且必须受到保护。
    • 如果是子类,它只能派生自满足这些条件并带有接口后缀的类。

    接口类永远不能直接实例化,因为它声明了纯虚方法。为了确保接口的所有实现都可以正确销毁,接口还必须声明一个虚拟析构函数(在第一条规则的例外情况下,这不应该是纯的)。有关详细信息,请参阅 Stroustrup,C++ 编程语言,第 3 版,第 12.4 节。

    查看 Google C++ Style Guide,“Multiple Inheritance”和“Interface”部分。 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-17
      • 1970-01-01
      • 2013-09-20
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      • 2019-10-03
      • 2014-01-28
      相关资源
      最近更新 更多