如何设置表示接口的类?这只是一个抽象基类吗?


当前回答

class Shape 
{
public:
   // pure virtual function providing interface framework.
   virtual int getArea() = 0;
   void setWidth(int w)
   {
      width = w;
   }
   void setHeight(int h)
   {
      height = h;
   }
protected:
    int width;
    int height;
};

class Rectangle: public Shape
{
public:
    int getArea()
    { 
        return (width * height); 
    }
};
class Triangle: public Shape
{
public:
    int getArea()
    { 
        return (width * height)/2; 
    }
};

int main(void)
{
     Rectangle Rect;
     Triangle  Tri;

     Rect.setWidth(5);
     Rect.setHeight(7);

     cout << "Rectangle area: " << Rect.getArea() << endl;

     Tri.setWidth(5);
     Tri.setHeight(7);

     cout << "Triangle area: " << Tri.getArea() << endl; 

     return 0;
}

结果:矩形面积:35三角形面积:17

我们已经看到了抽象类是如何根据getArea()定义接口的,另外两个类实现了相同的函数,但使用了不同的算法来计算特定于形状的面积。

其他回答

我还是C++开发的新手。我从Visual Studio(VS)开始。

然而,似乎没有人提到VS(.NET)中的__interface。我不太确定这是否是声明接口的好方法。但它似乎提供了额外的强制执行(文件中提到)。这样就不必显式指定虚拟TYPE Method()=0;,因为它将被自动转换。

__interface IMyInterface {
   HRESULT CommitX();
   HRESULT get_X(BSTR* pbstrName);
};

然而,我不使用它,因为我担心跨平台编译兼容性,因为它只在.NET下可用。

如果有人对此感兴趣,请分享。:-)

谢谢

在C++20中,可以使用概念而不是类。它比继承更有效率。

template <class T>
concept MyInterface = requires (T t) {
    { t.interfaceMethod() };
};

class Implementation {
public:
    void interfaceMethod();
};
static_assert(MyInterface<Implementation>);

然后您可以在函数中使用它:

void myFunction(MyInterface auto& arg);

限制是不能在容器中使用它。

C++中没有“接口”本身的概念。AFAIK,接口首先在Java中引入,以解决缺少多重继承的问题。事实证明,这个概念非常有用,在C++中使用抽象基类也可以达到同样的效果。

抽象基类是一个类,其中至少一个成员函数(Java语言中的方法)是使用以下语法声明的纯虚拟函数:

class A
{
  virtual void foo() = 0;
};

抽象基类不能实例化,即不能声明类A的对象。只能从A派生类,但任何不提供foo()实现的派生类也将是抽象的。为了停止抽象,派生类必须为其继承的所有纯虚拟函数提供实现。

请注意,抽象基类可以不仅仅是一个接口,因为它可以包含非纯虚拟的数据成员和成员函数。接口的等价物是一个抽象基类,没有任何数据成员,只包含纯虚拟函数。

而且,正如MarkRansom所指出的,抽象基类应该像任何基类一样提供虚拟析构函数。

考虑这一点的一个好方法是继承接口而不是继承实现。在C++中,您可以同时继承接口和实现(公共继承),也可以只继承实现(私有继承)。在Java中,您可以选择只继承接口,而不继承实现。

以上都是好答案。还有一件事你应该记住——你也可以有一个纯粹的虚拟析构函数。唯一的区别是你仍然需要实现它。

困惑的


    --- header file ----
    class foo {
    public:
      foo() {;}
      virtual ~foo() = 0;

      virtual bool overrideMe() {return false;}
    };

    ---- source ----
    foo::~foo()
    {
    }

你想这样做的主要原因是,如果你想提供接口方法,就像我所说的那样,但让重写它们成为可选的。

要使类成为接口类,需要一个纯虚方法,但所有的虚方法都有默认实现,因此唯一剩下的方法就是析构函数。

在派生类中重新实现析构函数根本没什么大不了的——我总是在派生类里重新实现一个析构函数,不管是虚拟的还是非虚拟的。

如果您只需要接口的静态绑定(没有虚拟的,没有接口类型本身的实例,接口仅作为指南):

#include <iostream>
#include <string>

// Static binding interface
// Notice: instantiation of this interface should be usefuless and forbidden.
class IBase {
 protected:
  IBase() = default;
  ~IBase() = default;

 public:
  // Methods that must be implemented by the derived class
  void behaviorA();
  void behaviorB();

  void behaviorC() {
    std::cout << "This is an interface default implementation of bC().\n";
  };
};

class CCom : public IBase {
  std::string name_;

 public:
  void behaviorA() { std::cout << "CCom bA called.\n"; };
};

class CDept : public IBase {
  int ele_;

 public:
  void behaviorB() { std::cout << "CDept bB called.\n"; };
  void behaviorC() {
    // Overwrite the interface default implementation
    std::cout << "CDept bC called.\n";
    IBase::behaviorC();
  };
};

int main(void) {
  // Forbid the instantiation of the interface type itself.
  // GCC error: ‘constexpr IBase::IBase()’ is protected within this context
  // IBase o;

  CCom acom;
  // If you want to use these interface methods, you need to implement them in
  // your derived class. This is controled by the interface definition.
  acom.behaviorA();
  // ld: undefined reference to `IBase::behaviorB()'
  // acom.behaviorB();
  acom.behaviorC();

  CDept adept;
  // adept.behaviorA();
  adept.behaviorB();
  adept.behaviorC();
  // adept.IBase::behaviorC();
}