在设计接口时,有人建议使用非虚拟接口模式。有人能简要介绍一下这种模式的好处吗?
发布于 2011-06-26 08:12:51
非虚拟接口模式的本质是拥有私有虚拟函数,这些函数由公共非虚拟函数(非虚拟接口)调用。
这样做的好处是,与派生类能够覆盖其接口的任何部分相比,基类对其行为有更多的控制。换句话说,基类(接口)可以为它所提供的功能提供更多的保证。
作为一个简单的例子,考虑一下具有两个典型派生类的优秀的老动物类:
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; }
};这使用了我们常用的公共虚拟接口,但它有一些问题:
std::cout << ... << std::endl;样板代码。speak()做了什么。派生类可能会忘记新行,或者将其写入cerr或其他任何内容。要解决此问题,您可以使用非虚拟接口,该接口由允许多态行为的私有虚拟函数补充:
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,我推荐你去看看。
发布于 2011-06-26 08:20:55
下面是一个更详细的wiki article it示例。其本质是,您可以在基类的中心位置确保重要的条件(如获取和释放锁),同时仍然允许从它派生,以通过使用私有或受保护的虚拟函数来提供不同的实现。
类层次结构的任何类的用户都将始终调用公共接口,该接口将调用分派到外部不可见的实现。
https://stackoverflow.com/questions/6481260
复制相似问题