[ About TopSites | Submit Site | Login
Sublime Directory
Topsites network : [ RSS Feeds directory | Free articles | Webdigity webmaster forums | Pagerank graphic | Whois database ]
RSS Feeds categories :
::  Arts & Humanities
::  Automotive
::  Business & Economy
::  Computers & Internet
     Hardware
     Internet
     Programming
     Security
     Software
     Wireless technology
::  Entertainment
::  Health & Fitness
::  Miscellaneous feeds
::  News - General
::  Politics & Government
::  Regional
::  Society & Culture
::  Sports
::  Technology & Science
::  Webmaster Resources
Submit a feed



JLR's Weblog

Description : No description for this item


Type : feed, version : uknown
RSS Feed adress : http://feeds.feedburner.com/Jlr-TipsTricksAndTics
Site Adress :
Build : Uknown
Generator : Blogger

Ranking : 0.00 ( 0 votes )
Rate this feed :


Relative sites :







Feed preview :

Why a Public Virtual Destructor


I started writing this as a reply tothis commentbyLen Holgate. However, it became such a long message I decided to promote it to a full post. Here is then, my response.

Hi, Len: thank you very much for your comments:

You wrote:

"Apart from the fact that I dislike the whole idea of using macros to somehow make abstract base classes into interfaces [...]"

It’s unfortunate that you didn't mention the reasons that make you “dislike the whole idea." I'm fully aware there are many bad and dangerous uses for macros, and that by generalization many people tend to be prejudiced against them, thus turning a suspicious eye on every macro they see. But I don't know what exactly your point was, not even if it was actually related to macros or not, so you leave me no choice but to pass on trying to respond it. :)

You do raise some clear points, though, which I’d like to address. First, you say:

”an abstract base class IS ALREADY an interface in C++”

Well, yes, it is... and at the same time, no, it isn’t.
We must first observe that "interface" is anoverloadedword. We use“interface” for too many different concepts, and for a meaningful discussion it's important to avoid confusing them, or to change from one meaning to another. For example, there is the usual OO meaning of "class interface" as the set of public members exposed by a class. Then there is the meaning of "class interface" as the entire class declaration, which in turn contains the "private interface", the "protected interface", and the already mentioned "public interface". Last, but not least, there are also "interface classes" with the meaning of abstract classes containing only pure virtual functions, which are also mentioned as "pure interfaces" byBjarne Stroustrupin hisC++ Style and Technique FAQ.

Precisely these "pure interfaces" is whatUsing Interfaces in C++ (I),(II), and(III)are about, and although pure interfaces are abstract base classes, clearlynot everyabstract base class is a pure interface. Every class with at least one pure virtual function is an abstract base class, but by definition, only those with nothing but pure virtual functions qualify as pure interfaces.

It’s true I'm also adding to these interfaces a convenient virtual destructor, and that leads us to your next point:

"You seem to be under the mistaken belief that their destructors must always be virtual."

Hmm… you seem to be under the mistaken belief that I'm under a mistaken belief. :)

I won't go so far as to say that interfaces must always have virtual destructors. However, I do say that because of the way these interfaces are used, I want all my interfaces to have a virtual destructor. But I’ll explain this better as I continue to address your points. You also said:

”They should only be virtual if you intend to delete an object that implements the interface via a pointer to that interface."


I can only agree with that. I have also read with attention the Herb Sutter’s article aboutVirtualityyou mentioned; I hadn’t read it before, but found it very interesting, especially as you suggested, the guideline #4. Let me quote here its bottom line:

"Either: a) you want to allow polymorphic deletion through a base pointer, in which case the destructor must be virtual and public; or b) you don't, in which case the destructor should be nonvirtual and protected, the latter to prevent the unwanted usage."

I fully agree with that too. Whether we are in the first situation or in the second situation is the key, and also where it seems you and I disagree. For instance, while talking about the first situation, you said:

"Mostly, I find that this isn't the case, in which case the destructor should be non virtual and protected so that the client of the interface is restricted from deleting the object via the interface..."


Once again, we need to make a distinction, now between two (at least) different cases in which interfaces are used. If we consider the case of COM interfaces, for example, the lifetime of objects that implement the interfaces are managed through reference counting; in the general case, each object deletes itself when the reference count reaches zero. As a result, for COM interfaces, a public destructor is not only unneeded but also undesired; giving a COM client the chance to destruct the object behind an interface is an obvious no-no. Furthermore, since the destructor will be normally invoked in the scope of the concrete implementer class itself (i.e.: delete this), the destructor doesn’t need to be virtual, either. In sum, this is clearly Sutter’s “case b”, and following his advice, if we were to declare a destructor in a COM interface, it should be non virtual and protected.

In practice, however, COM interfaces don’t even have a destructor.Don Box, for many the one and only COM expert, in hisInterface Pointers Considered Harmful[1] article published in the September 1995 issue of theC++ Report, after showing why declaring virtual destructors in the COM interfaces definitions“would have clearly been the wrong approach”, states that “a more reasonable solution would have been for IUnknown to provide a protected, non-virtual destructor with an empty implementation”, and also explains why, in spite of that, Microsoft’s “decision to not include protected destructors was”, in his opinion, “not without justification.” We should also note that the__interface keywordadded as a MS extension to the C++ compiler in VS7, which in my opinion was designed with COM interfaces in mind, doesn’t allow destructors of any kind, among other restrictions.

But there’s more in this “pure interface” beautiful world we are living than just COM interfaces, or to put it in more general terms, more than just interfaces implemented by objects with reference-counting lifetime management. The interfaces I’m talking about in these posts are not COM interfaces, but general purpose interfaces. I’m not using reference-counting, nor any other form of lifetime management, and so I do need interface clients to be able to make polymorphic deletions through interface pointers.

I talk about this inUsing Interfaces in C++ (II)but I might as well add some more colorful examples here. Suppose I’m writing a visual form editor. Think about the typical window showing a form, and a toolbox from which you can select new controls to add in the form. I don’t want the classes implementing the view and the document to be coupled to any particular implementation of controls. For example, I maywant the same view and document classes to be able to edit Windows forms, OSX forms, etc, and even within the same category I may want to use, depending on some additional criteria, different implementations of the family of controls. So I start by defining the interface every control must expose, regardless of its implementation:

DeclareInterface(IControl)
void Move(CPoint ptNewPos);
void Resize(CSize szNewSize);
void Draw(CDC* pDC) const;
/*
.
.
.
*/
EndInterface(IControl)

For each particular implementation of a family of controls, I’ll have afactory, which must implement a factory interface:

enum ControlType {BUTTON, COMBO, EDIT /* , ... */};

DeclareInterface(IControlFactory)
IControl* CreateControl(ControlType ctrlType) const;
EndInterface(IControlFactory)

One implementation of a family of controls might be something like this:

class WinControl : public CObject
,implements IControl
{
private:
CRect m_rPos;

// More data, Construction, Destruction
// Serialization, etc.

// [...]

// Basic IControl implementation
public:
void Move(CPoint ptNewPos)
{
m_rPos.OffsetRect(ptNewPos - m_rPos.TopLeft());
}

void Resize(CSize szNewSize)
{
m_rPos.BottomDown = m_rPos.TopLeft() + szNewSize;
}

void Draw(CDC* pDC) const
{
pDC->Rectangle(m_rPos);
}
};

class WinButton : public WinControl
{
// [...]

// Overrides Draw()
void Draw(CDC* pDC) const
{
// Draw a button control
}
};

class WinEdit : public WinControl
{
// [...]

// Overrides Draw()
void Draw(CDC* pDC) const
{
// Draw an edit control
}
};

The factory corresponding to this family would be:

class WinControlFactory : implements IControlFactory
{
// IControlFactory implementation
public:
IControl* CreateControl(ControlType ctrlType) const
{
switch (ctrType)
{
default:
return new WinControl();

case BUTTON:
return new WinButton();

case COMBO:
return new WinCombo();

case EDIT:
return new WinEdit();

/*
.
.
.
*/
}
}
};

Once a particular factory is selected, the controls are created through it as needed. Each created control is returned by the factory as an IControl pointer and added to the document, which stores it. Once the controls are no longer needed, the document is responsible for deleting them, and when doing so, it will be calling delete on the interface pointers, that is, doing a“polymorphic deletion through a base pointer” of each control.

But this isn’t the only case where such deletions could occur in this form editor, though. Suppose that in order to implement undo/redo functionality, thecommand patternis used. For each UI action, the document will be asked for a command responsible for executing it (and undoing it if needed). Once again, I don’t want anyone, being tied to a particular implementation of command. In particular, I don’t want the UndoManager, which is used for any editor and in any application, to know anything about (or depend on) the actual class of each command, or require them to be derived from any particular class,except for the abstract command interface.

DeclareInterface(IUndoableCommand)
void Do();
void Undo();
EndInterface(ICommand)

Now, these commands will be received through an IUndoableCommand pointer. The command will be executed and then stored by the UndoManager, which once the command becomes unneeded, deletes it through the interface pointer.

Given the ubiquity of this pattern of use in which objects are created in the heap, stored as interface pointers, and later deleted through those same pointers, I don’t want to defer the decision of adding a public virtual destructor until the coding of each and every class that implements an interface, where I may or may not remember to do it. Again, quoting from Herb Sutter’s article:

”If deletion, therefore, can be performed polymorphically through the base class interface, then it must behave virtually and must be virtual. Indeed, the language requires it - if you delete polymorphically without a virtual destructor, you summon the dreaded specter of "undefined behavior," a specter I personally would rather not meet in even a moderately well-lit alley, thank you very much.”


Since I clearly want to allow polymorphic destruction through the interfaces, their destructors must clearly be public and virtual.

Now, recalling the interface example I gave above:

DeclareInterface(IControl)
void Move(CPoint ptNewPos);
void Resize(CSize szNewSize);
void Draw(CDC* pDC) const;
/*
.
.
.
*/
EndInterface(IControl)

You might wonder why I don’t simply write it this other way:

class IControl
{
public:
virtual ~IControl() {}
virtual void Move(CPoint ptNewPos) = 0;
virtual void Resize(CSize szNewSize) = 0;
virtual void Draw(CDC* pDC) const = 0;
/*
.
.
.
*/
};

The answer is that if I’m using interfaces in the first place, is because I want to decouple things, and that includes decoupling of concerns. When I’m writing an interface, I’m focusing on describing a set of capabilities that implementers of the interface must have, and that’s all. I want the process of defininga new interface to be as straightforward and less error-prone as possible: a) this is an interface; b) these are its methods; c) enough said. Every other lower level detail such as not declaring any data members, declaring every method as public and virtual pure, not deriving from anything but other interfaces, and for the reasons explained above, having a public virtual destructor, should be already implied by my expressed intention of declaring an interface, and ideally, enforced by the compiler.

That’s what those so polemic macros (to some, almost kind of heretic), are intended to enable. They encapsulate, rather than obscure, and enforce, the low-level details of a design concept. And I love them for that.

Best regards, and thanks again for your comments.


[1] Since I couldn’t locate a working online version of this article, the link makes use of archive.org’sWayback Machine.


http://feedproxy.google.com/~r/Jlr-TipsTricksAndTics/~3/N9Gxn5Xmbk8...

I Can Already do That!


Some day around twenty years ago, back in the days when I knew absolutely nothing about computers and programming, I was nonetheless writing a sequence of statements in Basic– I don’t dare to call it a program. I’m talking about a time when, unlike now, there wasn’t a computer in almost every office and home, and kids didn’t start operating and programming computers long before their first love kiss.

I was at the time a young first-year college student in economics, and all my knowledge about what a computer was could be summarized in what I had so far seen in the movies. And I mean those times’ movies: a huge cabinet covering an entire wall and displaying a mystifying collection of tiny titillating colored lights.

But it was my fate that I got a job as the messenger boy for a computer hardware shop, and one day curiosity led me to a Basic Reference Manual besides an unoccupiedWang PC. Reading instruction descriptions in the manual and looking at the examples I began experimenting whit this computer thing after my working hours. Some days later I was able to paint a sequence of circles in the screen, varying its size and color, and making them zigzag and bounce on the screen borders. Trivial, yes, and absolutely useless too, but I was so proud of my recently acquired“programming skills” that I dared to show it to one of the engineers. He looked unemotionally at what I had written, and focused in a section that read something like this:

310 I = 1
320 CIRCLE (X+I, Y+I), 30, 15
330 I = I + 1
340 IF I<= 50 THEN GOTO 320

He then proceeded to show me how this could be expressed as:

310 I = 1
315 DO
320 CIRCLE (X+I, Y+I), 30, 15
330 I = I + 1
340 LOOP WHILE I<= 50

or even better as:

310 FOR I = 1 TO 50
320 CIRCLE (X+I, Y+I), 30, 15
330 NEXT

After he explained me how theseforandwhileworked, I looked at him with puzzlement.“But… isn’t that the same thing I had already written?” I humbly asked, thinking I was surely missing something. “It produces the same results, yes…” was his only response. “Then, what do I need that for? I can already do that!” I shoot back at him, all my humbleness suddenly lost.He didn’t respond. Instead, he gave me an enigmatic smile, a “you’ll eventually get to that, little grasshopper” kind of smile, and with that he walked away. It took me awhile, but I did get to it, and I always thank him for letting me figure it out by myself.

But learning why using aforconstruction was better than writing its equivalentif-gotocombination was only a part of what I got from that experience. I also learnt that rejecting something new just because“I can already do that”, is foolish and almost always a sign that I'm completely missing the point.

In software design and programming in particular, there are very few things, if any, that are absolutely needed in the sense that you can’t do it in some other way. But clearly some ways are better than others, at least in some situations, so why should I reject a proposed new way just because “I can already do that” in the older way?

We don’tneedstructured languages in order to write structured code, and we don’t evenneedstructured code in order to write a given program. Similarly, we don’tneedobject oriented languages to write code in an object oriented way, and of course we don’tneedobject oriented code either. I may or may not like object oriented programming, or structured programming, or any of the languages that support them, but rejecting any of those on the basis that“I can already do that” without them, makes no sense. Still, I’m sure that when those ideas were initially proposed, many objections of that kind were heard.

Whenever I’m presented with a new idea and I find myself thinking “I can already do that”, I remember those circles in Basic and force myself to think again without saying anything; I know I might be entirely missing the point. When it’s me presenting something new and I got “I can already do that”as a response, then I know it’s my time for a “you’ll eventually get the point, little grasshopper” silent smile.


http://feedproxy.google.com/~r/Jlr-TipsTricksAndTics/~3/aOYHhf79vMk...

Policy-Based Design in C++


I've just recently found an excellent article aboutPolicy-Based Design in C++byAndrei Alexandrescu.

Quoting from the article:
In brief, policy-based class design fosters assembling a class with complex behavior out of many little classes (called policies), each of which takes care of only one behavioral or structural aspect. As the name suggests, a policy establishes an interface pertaining to a specific issue. You can implement policies in various ways as long as you respect the policy interface.

Very interesting stuff, worth giving it a try.

 


http://feedproxy.google.com/~r/Jlr-TipsTricksAndTics/~3/in5bo_Dj544...

Using Interfaces in C++ (III - final, I promise)


[UPDATE 2005/06/01]I submitted thisarticleto CodeProject today.

Shortly after my last post, I did find a way to do what I said wasn’t possible: using the __interface keyword (a Microsoft extension) along with an enforced virtual destructor. For those interested in the topic, other resources related to using interfaces in C++ are included in this post too.

The solution I found was actually rather simple: the name for the desired interface is actually used to declare a class that contains a virtual destructor and inherits from an __interface that contains the actual methods. The macros are now defined as follows:

// cppinterfaces.h
 
#define DeclareInterface(name) __interface\
actual_##name {
 
#define EndInterface(name) };\
class name : public actual_##name {\
public:\
virtual ~name() {}\
};

Here is how you declare an interface using the above defined macros:

// ibar.h
 
#include "cppinterfaces.h"
 
DeclareInterface(IBar)
int GetBarData() const;
void SetBarData(int nData);
EndInterface(IBar)

As you may have noticed, these new macro definitions require using the name of the wanted interface (ie: IBar) twice, first for DeclareInterface(), and then for EndInterface(). This introduces an always undesired redundancy, which made me struggle for a while trying to eliminate but failed. If anyone finds a way to define the macros so as to avoid requiring the same name twice, please let me know.

On the other hand, providing you don’t mind sacrificing portability to anything but MS compilers starting from VS7, the new macros have many advantages over their predecessors, simply because every requirement for an interface (only pure virtual methods, no data members, virtual destructor for implementing classes) is now automatically enforced. You don’t even need to explicitly declare interface methods as virtual or pure virtual (“= 0”), although the compiler won’t complain if you do so.

Before closing the topic, I’d like to include some links to related resources, which I found while doing research for these three posts. I plan on submitting an article covering what I posted here to CodeProject too and I’ll update this post in order to include a link to it as soon as it becomes available.[UPDATE 2005/06/01]I submitted thisarticleto CodeProject today.

The techniques described here allow defining and implementing interfaces in C++ through the use of abstract base classes. Some people don’t like this as a solution because it forces every implementing class to have (and use) a virtual table and they find this unacceptable due to the space (the virtual table for each class) and performance (the indirection in each method call) penalties it imposes. As an alternative, Brian McNamaraand Yannis Smaragdakis from the Georgia Institute of Technology wrote a paper “Static interfaces in C++,” which was published in theFirst Workshop on C++ Template Programming, Erfurt, Germany, October 10 2000.

Christopher Diggins wrote aproposalfor a modification of the C++ language, in order to make it support interfaces without virtual functions. I have no idea whether this proposal was actually presented or considered by the standard committee.

Dr. Dobb's Journal August 1998, includes an article by Fred Wild, "Keeping interfaces and implementations separate," which discusses some ways to do so in C++ code.

Last but not least, the father of C++ Bjarne Stroustrup himself, made interesting comments about interfaces and C++ in aninterviewby Bill Venners in November 2003.

That’s all. I promise not to bother you with this interface stuff anymore. :)


http://feedproxy.google.com/~r/Jlr-TipsTricksAndTics/~3/XdPTZG_j4ZE...

Using Interfaces in C++ (II)


In the previouspostI wrote about a technique that, with the help of a few simple macros, allows using interfaces in C++ code, as you can do in Java or C#. Readermschaefraises a good point in hiscomment, which I respond here. A Microsoft extension introduced in VS7 is analyzed here too.

The main point inmschaef's comment is that since the macros don't enforce anything, and don't significantly improve readability, why bother with them at all. Well, if you look closely at theDeclareInterfaceandDeclareBasedInterfacemacros, you’ll note there is at least something being enforced there: every class implementing an interface will have a virtual destructor. You may or may not think this is important, but there are cases when the lack of a virtual destructor will cause problems. Consider the following code, for instance:

DeclareInterface(IBar)
public:
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;
}
}
};

There’s a factory to which you can ask to create an IBar implementation, depending on a BarType parameter. After using it, you are expected to delete the object; so far so good. Now consider how this is used in the main function of some application:

int main()
{
IBar* pBar = BarFactory::CreateBar(Foo);
 
pBar->SetName("MyFooBar");
// Use pBar as much as you want, and then
// ...
 
// just delete it when it's no longer needed
delete pBar;
}

What happens at the“delete pBar” line, depends on whether the actual class of that object has a virtual destructor or not. IfFoodoesn’t have a virtual destructor, the compiler will only generate a call toIBar’s implicit empty destructor, the destructor forFoowon’t be called, and thus you’ll have a memory leak. The virtual destructors in the interface declaration macros are there in order to avoid this situation; they ensure every class implementing an interface will also have a virtual destructor.

Now, if we are going to useDeclareInterface, it kind of makes sense to also useEndInterfaceto match with it, rather than a closing brace with no apparent opening one to match. The need for theInterfaceandimplementsmacros, which resolve toclassandpublic, respectively, could be objected as superfluous, but I find them to better express the actual intent of the code. If I write“Foo : public IBar” you can only read some inheritance there and nothing else. If on the other hand, I write “Foo implements IBar”, you can see it for its actual value and intent: the implementation of the interface concept, and not just any kind of class inheritance. I do find value in that.

To be fair, I’m suremschaefwas actually concerned with the other things these macros do not and cannot enforce: interfaces are expected to have only pure virtual functions and no instance data. But at least, if you write your interfaces usingDeclareInterfaceandEndInterface, the inclusion of any instance data or non virtual pure function should be easy to spot. In Joel Spolsky’s word, these macros also help by“making wrong code look wrong.”

C++ Interfaces support in VS7


The folks at Microsoft must have felt the same need to enforce those restrictions on classes used as interfaces, judging from the introduction in VS7 of the__interfacekeyword as a new Microsoft extension to the C++ compiler. In thedocumentationthey define a Visual C++ interface as follows:
  • Can inherit from zero or more base interfaces.
  • Cannot inherit from a base class.
  • Can only contain public, pure virtual methods.
  • Cannot contain constructors, destructors, or operators.
  • Cannot contain static methods.
  • Cannot contain data members; properties are allowed.

And they note:“A C++ class or struct could be implemented with these rules, but__interfaceenforces them.” So, if you are not worried by portability, you could use this extension and have the compiler enforce what needs to be enforced, right? Wrong.

Remember that bit about the need for virtual destructors?__interfacedoes not add a virtual destructor for the implementing class. Couldn’t we just use__interfacein theDeclareInterfacemacro definition, so as to have the best of both worlds? Read again the definition:“cannot contain constructors, destructors, or operators”.

I can understand why MS didn’t see the need for virtual destructors in interfaces. If you look at the samples in the documentation, it’s pretty clear from where they are COMing. They obviously created this extension with COM interfaces in mind and you never use delete with them, because they are count referenced objects, which call delete on themselves when the count reaches zero. So,__interfacemay be useful for COM interfaces but it’s neither intended nor suitable for the general purpose interfaces we are discussing here.


http://feedproxy.google.com/~r/Jlr-TipsTricksAndTics/~3/DyScAMdy-ME...

Using Interfaces in C++ (I)


The distinction between classes and interfaces is a powerful language feature present both in Java and C# (and probably many other languages) but not in C++. For years, our team has been using a "methodological" implementation of the interface concept for C++. Starting in VS7, there's also an MS extension pointing in the same way, allowing the compiler to enforce most of the defining characteristics of an interface, and of course, managed extensions for C++ supports the definition and implementation of .NET interfaces too. However there are some subtle and not so subtle differences between each of these mechanisms that you should be aware of.

Many years ago, around November 1999, I defined a way to declare interfaces for C++, and to make classes implement them, just by using a few macros and making sure some basic rules were followed. I should make clear I don't claim to be the "inventor" of this technique or anything like that. Although it was independently developed, mostly with the invaluable advice of Roberto Lublinerman, I later found many internet articles, which described more or less the same ideas, and at least some of them were dated way before we had even came to think about it.

More recently, I wrote about this technique in a rather lengthyusenet post, but let me summarize it here.

First, some macros are defined in a header file, which you'll probably want to include in your precompiled headers:

#define Interface class
 
#define DeclareInterface(name) class name\
{\
public:\
virtual ~name() {}
 
#define DeclareBasedInterface(name, base) class name\
: public base\
{\
public:\
virtual ~name() {}
 
#define EndInterface };
 
#define implements public

Using these macros, you can declare an interface in the following way:

DeclareInterface(IBar)
public:
virtual int GetBarData() const = 0;
virtual void SetBarData(int nData) = 0;
EndInterface

Then you can declare a class that implements this interface with something like:

class Foo : public BasicFoo, implements IBar
{
// Construction&Destruction
public:
Foo(int x) : BasicFoo(x)
{
}
 
~Foo();
 
// IBar implementation
public:
virtual int GetBarData() const
{
// stuff...
}
 
virtual void SetBarData(int nData)
{
// stuff...
}
};


Easy, isn't it? Without much effort you are now able to use interfaces in C++. However, as they aren't directly supported in the language, you are supposed to follow some rules, which can't be automatically enforced at compilation time. After all, all the compiler can see is the use of plain old multiple inheritance. So, here are the rules:
  • When declaring a class, use the first base class for "structural" inheritance (the "is a" relationship) if there is one, as you normally do (eg: CFrameWnd derives from CWnd, CBitmapButton derives from CButton, YourDialog derives from CDialog, and so on). This is specially important if you are deriving from MFC classes; declaring them as the first base class avoids breaking MFC's RuntimeClass mechanism.
  • Use additional base classes for interface implementation, as many as you want or need (eg: class Foo : public BasicFoo, implements IBar, implements IOther, implements IWhatever, ...)
  • Do not declare any member variables inside interfaces. Interfaces are intended to express behaviour, not data. Besides, this helps avoid some problems if you were to use multiple "structural" inheritance and happened to be deriving more than once from the same interface.
  • Declare all member functions in interfaces as virtual pure (ie: with "= 0"). This ensures every instantiable class that declares to implement an interface does it for all its functions. It's OK to partially implement an interface in an abstract class (in fact it will be abstract anyway if you do so) as long as you implement the remaining functions in the derived classes you actually intend to instantiate. Since the interfaces offer no "basic" implementation, you need to be sure everyone that receives a pointer to some interface will be able to call any of its members; declaring all your interface members as virtual pure will enforce this at compile time.
  • Do not derive your interfaces from anything but other interfaces. You can use the DeclareBasedInterface() macro for that. Normal classes can choose to implement the basic interface or the derived (extended) one; the latter of course means implementing both.
  • Assigning a pointer to a class that implements some interface to a pointer to that interface requires no casting, as you will be actually casting to a base class. Doing it the other way though (from an interface pointer to a pointer to the class implementing it), will require an explicit cast, as you will be casting to a derived class. Since you will be in fact using multiple inheritance (even if for virtually every other practical need you can think of it as single inheritance plus interace implementations), these casts can't be done the "old" way, because they may need different actual memory values. However, enabling Run-Time Type Information (/GR compiler option) and using dynamic casts works fine and it's of course safer anyway.
  • In fact the use of dynamic_cast will give you a way to ask any object or interface whether it implements a given interface or not.
  • You need to be careful to avoid name conflicts between functions in different interfaces, as it isn't easy to detect and resolve those conflicts if you have a class implementing both.


http://feedproxy.google.com/~r/Jlr-TipsTricksAndTics/~3/nEzCiM4sljU...

Topsites network is not affiliated in any way with the authors of this feed, and the copyrights of these feeds are owned by their respective authors
[ About TopSites | Link to us | Submit Site | Latest Additions | Random Site | Privacy Policy | Contact us ]
Sponsored by Homes for sale Toronto, Calgary Dentist, Toronto Dentist , Dentist in Toronto, Project Management , Developed by HumanWorks © 2005 - 2014 TopSites