[ACCEPTED]-Non-virtual interface design pattern in C#/C++-non-virtual-interface
The essence of the non-virtual interface 22 pattern is that you have private virtual functions, which 21 are called by public non-virtual functions (the non-virtual 20 interface).
The advantage of this is that 19 the base class has more control over its 18 behaviour than it would if derived classes 17 were able to override any part of its interface. In 16 other words, the base class (the interface) can 15 provide more guarantees about the functionality 14 it provides.
As a simple example, consider 13 the good old animal class with a couple 12 of typical derived classes:
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; }
};
This uses the 11 usual public virtual interface that we're 10 used to, but it has a couple of problems:
- Each derived animal is repeating code -- the only part that changes is the string, yet each derived class needs the whole
std::cout << ... << std::endl;
boilerplate code. - The base class can't make guarantees about what
speak()
does. A derived class may forget the new line, or write it tocerr
or anything for that matter.
To 9 fix this, you can use a non-virtual interface 8 that is supplemented by a private virtual 7 function that allows polymorphic behaviour:
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!"; }
};
Now 6 the base class can guarantee that it will 5 write out to std::cout
and end with a new line. It 4 also makes maintenance easier as derived 3 classes don't need to repeat that code.
Herb 2 Sutter wrote a good article on non-virtual interfaces that I would recommend checking 1 out.
Here is a wiki article it a bit more in details with 10 some examples. The essence is that you can 9 ensure important conditions (like obtaining 8 and releasing locks) in a central place 7 in your base class while still allowing 6 to derive from it to provide different implementations 5 by using private or protected virtual functions.
Users 4 of any class of the class hierarchy will 3 always call the public interface which dispatches 2 the calls to the not externally visible 1 implementations.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.