Home:ALL Converter>How to implement an interface class using the non-virtual interface idiom in C++?

How to implement an interface class using the non-virtual interface idiom in C++?

Ask Time:2010-04-29T15:49:10         Author:andreas buykx

Json Formatter

In C++ an interface can be implemented by a class whose methods are pure virtual.

Such a class could be part of a library to describe what methods an object should implement to be able to work with other classes in the library:

class Lib::IFoo
{
    public:
        virtual void method() = 0;
};

:

class Lib::Bar
{
    public:
        void stuff( Lib::IFoo & );
};

Now I want to to use class Lib::Bar, so I have to implement the IFoo interface.

For my purposes I need a whole of related classes so I would like to work with a base class that guarantees common behavior using the NVI idiom:

class FooBase : public IFoo // implement interface IFoo
{
    public:
        void method(); // calls methodImpl;

    private:
        virtual void methodImpl();
};

The non-virtual interface (NVI) idiom ought to deny derived classes the possibility of overriding the common behavior implemented in FooBase::method(), but since IFoo made it virtual it seems that all derived classes have the opportunity to override the FooBase::method().

If I want to use the NVI idiom, what are my options other than the pImpl idiom already suggested (thanks space-c0wb0y).

Author:andreas buykx,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/2735563/how-to-implement-an-interface-class-using-the-non-virtual-interface-idiom-in-c
Michael Anderson :

I think you've got your NVI pattern around the wrong way: \nhttp://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface\n\nNot sure if that solves your issue though.\n\nclass IFoo\n{\n public:\n void method() { methodImpl(); }\n private:\n virtual void methodImpl()=0;\n};\n\nclass FooBase : public IFoo // implement interface IFoo\n{\n private:\n virtual void methodImpl();\n};\n\n\nHere's an example of why you might do this using a reader that reads from XML and another from DB. Note that common structure is moved into the NVI readFromSource, while non-common behaviour is moved into the private virtual getRawDatum. This way logging and error checking is only needed in the one function.\n\nclass IReader\n{\n public:\n // NVI\n Datum readFromSource()\n {\n Datum datum = getRawDatum();\n if( ! datum.isValid() ) throw ReaderError(\"Unable to get valid datum\");\n logger::log(\"Datum Read\");\n return datum;\n }\n private:\n // Virtual Bits\n Datum getRawDatum()=0;\n};\n\nclass DBReader : public IReader\n{\n private:\n Datum getRawDatum() { ... }\n};\n\nclass XmlReader : public IReader\n{\n private:\n Datum getRawDatum() { ... }\n};\n",
2010-04-29T07:57:15
sbi :

Commonly, the reason for using the NVI (sometimes also called \"Template Method\") is that derived classes should only change a part of the base class' behavior. So what you do is this: \n\nclass base {\n public:\n void f()\n {\n // do something derived classes shouldn't interfere with \n vf();\n // do something derived classes shouldn't interfere with \n vg();\n // do something derived classes shouldn't interfere with \n vh();\n // do something derived classes shouldn't interfere with \n }\n private:\n virtual void vf(); // might be pure virtual, too\n virtual void vg(); // might be pure virtual, too\n virtual void vh(); // might be pure virtual, too\n};\n\n\nDerived classes can then plug into f() at the spots they are meant to and change aspects of f()'s behavior, without messing up its fundamental algorithm. ",
2010-04-29T07:56:42
DS. :

It may be confusing that once a method is declared as virtual in a base class, it automatically becomes virtual in all derived classes, even if the virtual keywords is not used there. So in your example, both methods of FooBase are virtual.\n\n\n ... to deny derived classes the\n possibility of overriding the common\n behavior implemented in\n FooBase::method()...\n\n\nIf you can get rid of IFoo, and just start the hierarchy with FooBase with a non-virtual method, that would do it. But it looks like you want to allow direct children of IFoo to override method(), but to prevent children of FooBase to override it. I don't think that's possible.",
2010-04-29T09:25:13
yy