首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#/C++中的非虚拟界面设计模式

C#/C++中的非虚拟界面设计模式
EN

Stack Overflow用户
提问于 2011-06-26 07:57:51
回答 2查看 6.5K关注 0票数 24

在设计接口时,有人建议使用非虚拟接口模式。有人能简要介绍一下这种模式的好处吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-06-26 08:12:51

非虚拟接口模式的本质是拥有私有虚拟函数,这些函数由公共非虚拟函数(非虚拟接口)调用。

这样做的好处是,与派生类能够覆盖其接口的任何部分相比,基类对其行为有更多的控制。换句话说,基类(接口)可以为它所提供的功能提供更多的保证。

作为一个简单的例子,考虑一下具有两个典型派生类的优秀的老动物类:

代码语言:javascript
复制
class Animal
{
public:
    virtual void speak() const = 0;
};

class Dog : public Animal
{
public:
    void speak() const { std::cout << "Woof!" << std::endl; }
};

class Cat : public Animal
{
public:
    void speak() const { std::cout << "Meow!" << std::endl; }
};

这使用了我们常用的公共虚拟接口,但它有一些问题:

  1. 每个派生的动物都在重复代码--唯一变化的部分是字符串,但是每个派生类都需要完整的std::cout << ... << std::endl;样板代码。
  2. 基类不能保证speak()做了什么。派生类可能会忘记新行,或者将其写入cerr或其他任何内容。

要解决此问题,您可以使用非虚拟接口,该接口由允许多态行为的私有虚拟函数补充:

代码语言:javascript
复制
class Animal
{
public:
   void speak() const { std::cout << getSound() << std::endl; }
private:
   virtual std::string getSound() const = 0;
};

class Dog : public Animal
{
private:
   std::string getSound() const { return "Woof!"; }
};

class Cat : public Animal
{
private:
   std::string getSound() const { return "Meow!"; }
};

现在基类可以保证它将写入std::cout并以新行结束。它还使维护变得更容易,因为派生类不需要重复这些代码。

Herb Sutter写了a good article on non-virtual interfaces,我推荐你去看看。

票数 49
EN

Stack Overflow用户

发布于 2011-06-26 08:20:55

下面是一个更详细的wiki article it示例。其本质是,您可以在基类的中心位置确保重要的条件(如获取和释放锁),同时仍然允许从它派生,以通过使用私有或受保护的虚拟函数来提供不同的实现。

类层次结构的任何类的用户都将始终调用公共接口,该接口将调用分派到外部不可见的实现。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6481260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档