在C ++中记录接口的位置?

时间:2013-10-16 08:20:23

标签: c++ interface

我有更多的Java背景,因此让我用Java示例来说明。假设存在以下代码:

interface iFoo {
    /* Do foo */
    void foo();
    /* Do bar */
    void bar();
}

class A implements iFoo {
    void foo() {};
    void bar() {};
}

class B<iFoo> {
    iFoo foo;
    B() {
        foo.foo();
        foo.bar(); 
    } 
} 

//somewhere in the code:
B b = new B<A>();

现在,如果我想实现一个可以用作B的类型参数的类C,我知道C必须实现iFoo。因此,我去那里,按照合同约定,所有必要的文件将在那里(我需要实现哪些方法,有什么签名加内联文档。

在C ++中,它看起来像这样(如果我错了,请纠正我):

class A {
public:
     void foo();
     void bar();
}

template<class T>
class B {
public:
    T foo;
    B() {
        foo.foo();
        foo.bar(); 
    } 
} 

//somewhere in the code:
B *b = new B<A>();

哪里是记录B对T的期望的最佳位置?或者反过来说,如果我有A和B并希望实现一个作为类型参数传递给B的类C,我如何找出B对T的期望?上面当然是一个非常简单的例子,想象一下更大更复杂的类。

4 个答案:

答案 0 :(得分:5)

在C ++中,纯抽象接口类看起来像这样:

struct IFoo
{
    virtual void foo() = 0;
    virtual void bar() = 0;

    virtual ~IFoo() {}
};

然后你像普通类一样继承它

class A : public IFoo
{
public:
    void foo();
    void bar();
};

答案 1 :(得分:3)

我想说文档的好地方是定义类的头文件。您的库的用户将查看头文件以查看界面,这是她应该找到文档的位置,包括整个类或模板以及公共成员。

整个班级或模板以及每个公共成员都应该有详细说明目的,假设,先决条件等的文件。

示例:

<强> foo.h中:

// The "Foo" template implements a gizmo according to Smith, Jones et al.
// A Foo<T> can be used as a drop-in replacement for the usual Zip<T>.
//
// The template parameter T must be a complete object type which is
// assignable and copyable.
template <typename T>
class Foo
{
public:
    // Reflect the template parameters
    using type = T;
    using refence = T &;

    // Constructs a Foo with a given state of being active, a given age
    // and an identifier that represents its glurgh.
    Foo(bool active, int age, char id);

    // Perform the magic act of foo.
    // It is safe to call this function multiple times concurrently.
    // Returns the number of bars.
    //
    // Intended usage:
    //
    //    Foo x(false, 10, 'a');
    //    registerGlobally(x);
    //    x.activate();
    //    return x.perform();
    //
    int perform();

private:
    // ...
};

理想情况下,如果没有其他参考资料,手册或教程,用户应该能够通过查看标题来确定如何使用该类。如果您遵守纪律并且并行维护适当的参考手册,您可以不使用示例,但必要的信息(参数的含义和要求,返回值的含义)应该在那里

当您从抽象基类公开继承时,这当然意味着基类已包含所有接口文档,并且您不需要重复一般信息。但是,您仍然应该在具体的覆盖范围内留下简短的评论,说明他们在实施方面的具体做法。


如果希望模板参数满足某些约束,例如从某个基类派生,则可以使用类型特征,SFINAE和模板元编程以编程方式强制执行。您仍应以人类可读的形式记录模板参数的要求,但在代码中强制执行此类约束是很好的卫生。

答案 2 :(得分:0)

您可以使用虚拟方法执行与C ++中的接口相同的操作,将=0放在方法定义的末尾,您就拥有了有效的接口。 (它实际上是一个必须派生的基类,因为它本身无法实例化,在C ++术语中称为“abstract base class”。)。

但是这给了你答案,没有什么可以阻止你说A是基础界面并使用它作为'B期望T'的定义。因此,如果A有两个方法,foo()和bar(),那么它就是它提供的东西,这就是从A派生的所有类也都有的。

答案 3 :(得分:0)

你可以使用像Joachim建议的界面,但不幸的是,C ++中没有办法强制执行它,就像你在Java中那样。所以你必须把它记录为评论,比如函数或某个地方。