一种在C ++中强制使用接口的方法

时间:2011-05-17 23:05:39

标签: c++ interface

在C ++中,假设我有一个类 Derived ,它实现了一个接口类 BaseInterface ,其中 {{1} } 只有纯虚函数和虚析构函数:

BaseInterface

class BaseInterface { public: virtual void doSomething() = 0; ~BaseInterface(){} }; class Derived : public BaseInterface { public: Derived() {} ~Derived(){} protected: virtual void doSomething(); private: int x; }; 类层次结构之外的任何类都不应直接调用Derived,即只能通过Derived::doSomething()类以多态方式访问它。为了执行此规则,我已对BaseInterface进行了保护。这很有效,但我正在寻找关于这种方法的意见/赞成。

谢谢!

5 个答案:

答案 0 :(得分:9)

我认为您正在寻找非虚拟接口(NVI)模式:调用受保护或私有public实现的virtual非虚拟接口:

class BaseInterface
{
  public:
    virtual ~BaseInterface(){}
    void doSomething() { doSomethingImpl(); }

protected:
    virtual void doSomethingImpl() = 0;
};

class Derived : public BaseInterface
{
  public:
    Derived() {}
    virtual ~Derived(){}

  protected:
    virtual void doSomethingImpl();

  private:
    int x;
};

答案 1 :(得分:3)

如果它是界面的一部分,为什么你不希望用户调用它?请注意,实际上,他们可以调用它:static_cast<BaseInterface&>(o).doSomething()只是说o.doSomething()的一种尴尬方式。 使用接口有什么意义...如果对象满足界面,那么你应该能够使用它,还是我错过了什么?

由于您实际上并没有阻止任何人调用这些方法,因此我没有看到使代码更复杂的问题(类的类和用户)没有特别的原因。请注意,这与非虚拟接口完全不同,因为在这个成语中,虚拟功能无法公开访问(在任何级别),而在您的情况下,目的是允许访问,并使其变得麻烦。

答案 2 :(得分:2)

您正在做的事情也在标准ISO / IEC 14882:2003(E)11.6.1中提到并且相信您是正确的。除了事实之外,在给定的示例中,成员函数不是纯虚拟的。它应该适用于纯虚函数,AFAIK。

  

虚函数的访问规则(第11节)由其声明确定,不受稍后覆盖它的函数规则的影响。

[Example:

   class B 
   { 
     public:
     virtual int f();
   };

   class D : public B 
   { 
     private:
     int f();
   };

   void f() 
   {
     D d; 
     B* pb = &d; 
     D* pd = &d;

     pb->f(); // OK: B::f() is public, 
              // D::f() is invoked

     pd->f(); // error: D::f() is private
   }

—end example]
  

使用用于表示的表达式类型在呼叫点检查访问   调用成员函数的对象(上例中为B *)。成员函数在定义它的类中的访问(上例中的D)通常是未知的。

答案 3 :(得分:1)

关键是代码的其余部分。只接受BaseInterface *作为任何需要doSomething()调用的方法的参数。客户端程序员被迫从接口派生出来以编译代码。

答案 4 :(得分:0)

这对我没有意义。无论您调用哪个指针doSomething(),您仍然可以使用大多数派生类中定义的方法。请考虑以下情形:

class BaseInterface
{
  public:
    virtual void doSomething() = 0;
    ~BaseInterface(){}
};

class Derived : public BaseInterface
{
  public:
    Derived() {}
    ~Derived(){}

      virtual void doSomething(){}

  private:
    int x;
};

class SecondDerived : public Derived
{
  public:
    SecondDerived() {}
    ~SecondDerived(){}

  private:
    int x;
};

int main(int argc, char* argv[])
{
    SecondDerived derived;
    derived.doSomething(); //Derived::doSomething is called

    BaseInterface* pInt = &derived;
    pInt->doSomething(); //Derived::doSomething is called

    return 0;
}