Using interfaces in C + +

Source: Internet
Author: User
Tags faa

Object-oriented languages such as Java provide interface to implement interfaces, but C + + does not have such a thing, although C + + through the pure virtual base class implementation interface, such as COM C + + implementation is through the pure virtual base class implementation (of course, MFC COM implementation using nested classes), But we prefer to see something like interface. A workaround is described below.

First we need some macros:

//
Interfaces.h
//

#define INTERFACE Class

#define DECLAREINTERFACE (name) Interface name {\ \
Public: \
Virtual ~name () {}

#define DECLAREBASEDINTERFACE (name, Base) class name:
Public Base {\
Public: \
Virtual ~name () {}

#define ENDINTERFACE};

#define Implements Public


With these macros, we can define our interface in this way:

//
IBar.h
//

Declareinterface (IBar)
virtual int Getbardata () const = 0;
virtual void setbardata (int ndata) = 0;
Endinterface

is not much like MFC message map Those macros Ah, familiar with MFC friends must not be unfamiliar.

Now we can implement our interface as follows:

//
Foo.h
//

#include "BasicFoo.h"
#include "IBar.h"

Class Foo:public Basicfoo, Implements IBar
{
Construction & Destruction
Public
Foo (int x): Basicfoo (x)
{
}

~foo ();

IBar implementation
Public
virtual int getbardata () const
{
Add your code here
}

virtual void setbardata (int ndata)
{
Add your code here
}
};

Well, it's easy, it doesn't take a lot of effort and we can use the interface in C + +. However, since this is not a feature directly supported by the language itself, we need to follow some rules:
A) When declaring a class, if your class inherits from another class in addition to inheriting from the interface class (structural inheritance, or is a relationship), then use this class as the first base class, as we normally do, such as CFrameWnd from CWnd,CBitmapButtonInherit from CButton, CMyDialog inherit from Cdialong. This is especially important when you want to derive from the MFC class, declaring them as the first base class to avoid destroying MFC's runtimeclass mechanism.
b) The rest of the base class is immediately followed by how much, if you need it. Such as:class Foo:public Basicfoo, implementsIBar, implementsIother, implementsIwhatever, ...
c) Do not declare any member variables inside the interface class. The interface class is used only to describe behavior, not data. When you want to do multiple inheritance, you can avoid data members being inherited multiple times from the same interface class.
d) All member functions of the interface class are defined as pure virtual functions. This ensures that your implementation class implements all of these functions, and of course you can implement some functions in an abstract class, as long as you implement the rest of the functions in your derived class.
e) do not derive your interface class from any other class except the interface class.declarebasedinterface () can do this. A generic class can choose to implement a base interface or a derived interface, and the latter means that both are implemented.
f) Assigning a pointer to a class that implements an interface to a pointer to that interface class does not require coercion of type conversions, but in turn assigns a pointer to an interface class to a class that implements the interface requires an explicit coercion type conversion. In fact, we might use multiple inheritance so that we can't use old-fashioned conversions for these conversions. However, using run-time type information (using the/GR option) and dynamic type conversion can be a good job and certainly more secure.
g) In addition, Dynamic_cast provides you with a way to query whether an object or interface implements a specified interface.
h) You also have to be very careful to avoid naming conflicts for different interface functions.

If you look closely at declareinterface and Declarebasedinterfaca macros you will find that one operation is necessary: each interface class has a virtual destructor. You might think it's not important, but without this it could lead to some problems, and take a look at the following example: as you can see, there is a class factory that creates a Ibar implementation based on Bartype, and you certainly want to delete the object when you're done with it. You will do as follows:

int main ()
{
ibar* PBar = Barfactory::createbar (Foo);

Pbar->setname ("Myfoobar");
Use PBar as much as you want,
//

And then just delete it ' s no longer needed
Delete PBar; oops!
}

What Deletepbar does depends on whether the object has a virtual destructor. If Foo does not have a virtual destructor, only Ibar's implicit null destructor is called, and the destructor for Foo is not called, so a memory leak occurs. The declaration of a virtual destructor in an interface class avoids this condition, and it ensures that each class that implements the interface has a virtual destructor.

When you use DECLAREINTERFAC, remember to use Endinterface to match it. Interface macros and implements macros just replace class and public, which seems redundant, but I think they express the intent of the code more clearly. If I write this: classfoo:public IBar, you might think it's just a simple inheritance; but if I write this: class Foo:implements IBar, you'll see its actual value and intent---it's an implementation of an interface, not a simple inheritance. Declareinterface (IBar)
Virtual LPCTSTR GetName () const = 0;
virtual void SetName (lpctstr name) = 0;
Endinterface

Class Foo:implements IBar
{
Internal data
Private
char* M_pname;

Construction & Destruction
Public
Foo ()
{
M_pname = NULL;
}

~foo ()
{
Releasename ();
}

Helpers
Protected
void Releasename ()
{

if (m_pname! = NULL)
Free (m_pname);
}

IBar implementation
Public
Virtual const char* GetName () const
{
Return M_pname
}

virtual void SetName (const char* name)
{
Releasename ();
M_pname = _strdup (name);
}
};

Class Barfactory
{
Public
Enum Bartype {Faa, Fee, Fii, Foo, Fuu};

Static IBar Createnewbar (Bartype bartype)
{
Switch (bartype)
{
Default
Case FAA:
return new Faa;
Case FEE:
return new Fee;
Case FII:
return new Fii;
Case Foo:
return new Foo;
Case FUU:
return new Fuu;
}
}
};

Using interfaces in C + +

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.