|
here's one i've used a few times:
i have a dialog class (CMyDlg) that uses some other class to do some processing. if that processing takes a long time, it's nice to show a progress dialog. but, only the worker class knows the progress status, so i need a way to get that info back to the dialog. in C, i'd just use a callback function (but in C++, that's not nice).
so, i make a little class like this:
class CProgressSink
{
public:
virtual bool Progress(int iCurrent, int iTotal) = 0;
};
and i multiply inherit my dialog class from CProgressSink, implementing the Progress function to do whatever progress updates i need (update a progress bar, show some text, pump some UI messages, etc).
bool CMyDlg::Progress(int iCur, int iTotal)
{
TRACE("%d of %d\n", iCur, iTotal);
return true;
}
at the same time, i've told my worker class to accept a pointer to a CProgressSink as a parameter in one of its ctors:
class CMyWorkerClass
{
CMyWorkerClass (CProgressSink *pSink = NULL) {m_pSink = pSink;}
};
when i create the worker class object in CMyDlg, i can tell it where to send its bloody progress messages:
CMyWorkerClass thingy(this);
so when the worker class is working, it tests to see if it has a valid CProgressSink pointer. if it does, it calls CProgressSink::Progress with the current progress state.
the nice thing about this is that if i want to use the worker class from some other class (another worker class, for example), i just inherit that new class from CProgressSink and tell the worker class that the new class wants to be notified of progress events.
you could make CMyWorkerClass take a reference (or pointer) to a CMyDlg class, instead of adding the CProgressSink class. but that means you can only send Progress events back to CMyDlgs. while, for not much more work (like 5 lines more), you get the flexibility to send progress state to any class you can create.
now, some people would do this with a worker thread, but i think that's overkill in many cases. you could also do this with a C callback function (passing a "this" pointer around), but that's a bit scary.
-c
Smaller Animals Software, Inc.
You're the icing - on the cake - on the table - at my wake. Modest Mouse
|
|
|
|
|
I've used it in our current project. I've implemented a scripting engine so that users can write Python scripts to automate the application. Since the data access speed is very slow in Python compared to compiled code, I've also provided the ability for users to write DLLs that implement commands accessible from Python through the application.
In my implementations, objects accessible through Python are derived from CPythonObject (my own). Objects accessible through the DLL command extensions implement a custom interface (non-COM) called I<something>.
For instance, I have an "area" object accessible to both Python and the DLL interface. The CArea object is derived from CPythonObject and IArea.
I think that there is a time and a place for MI. You just have to recognize the need.
J
|
|
|
|
|
Maybe I'm in the minority, but I use MI very often. Here's a simple example:
My apps often serialize various kinds of objects which eventually need to be presented to and manipulated by a GUI, typically tree and list controls. The objects are uniquely identified by id's (which happen to be unsigned longs, but that's immaterial) and also have non-unique names.
These objects multiply inherit from IIdentifiable and INamed , which are "interfaces" (i.e. classes with no data members, and whose methods are all pure virtual). My GUI elements know how to display any kind of INamed object because they can get athe object's name by calling getName() . The item data field of each GUI element stores the object's id, retrieved via getId() which is a method of IIdentifiable .
While C# and Java may not allow multiple inheritance, they allow objects to implement any number of interfaces, which is a safe way of exposing multiple behaviors. This is what I've done in the above C++ example.
One should exercise caution before settling on one side of the fence over questions like "do you use MI?" and "do you use goto s". Both concepts can be both used and abused.
/ravi
"There is always one more bug..."
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
Hi,
There is a classic C++ book, called "Desing Patterns", there you can find quite good patters that work pretty cool with Multiple inheritance, and add real power to your code.
Greetings
Braulio
|
|
|
|
|
I see 15 people so far have said they intentionally avoid it. Why? Is there something bad about MI?
- Matt Newman
-Sonork ID: 100.11179:BestSnowman
†
|
|
|
|
|
I think there is some kind of thinking among certain people that MI breaks the OOP concept.
Nish
My miniputt high is now 29
I do not think I can improve on that
My temperament won't hold
www.busterboy.org
|
|
|
|
|
I think many folks have an issue dealing with virtual base classes and method name clashes.
I dont have any problem with them and use them extensively. Perhaps because I have no choice because ATL is based on MI.
I used to code a lot in Java. One of the things I hated about Java was the lack of MI. If you had a CFeline and a CWild, it seems natural that CTiger would inherit all the properties of CFeline and CWild, and hence MI from the two classes.
With Java and C# you would have to use interfaces (or the C# equivalent), but that is painful and not very intuitive to me.
|
|
|
|
|
MI can result in hard to maintain code if used naively, and can result in easily extensible (and thereby manageable) code if used properly. Here's a nice discussion on the subject.
/ravi
"There is always one more bug..."
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
|
And I was the first to vote that way I guess it pays being up late at night at whatever time it happened to be.
James
Sonork ID: 100.11138 - Hasaki
"Smile your little smile, take some tea with me awhile.
And every day we'll turn another page.
Behind our glass we'll sit and look at our ever-open book,
One brown mouse sitting in a cage."
"One Brown Mouse" from Heavy Horses, Jethro Tull 1978
|
|
|
|
|
The real truth is that MFC says "we don't use it" and all other people therefore don't use it, because:
a) what MFC says, must be correct or
b) otherwise they would write code that does not work with MFC anymore.
--
See me: www.magerquark.de
|
|
|
|
|
|
Really? at which class should I look, to see it?
(or do you mean "derive from CWnd AND nothing else" counts already as mutliple inheritance? )
--
See me: www.magerquark.de
|
|
|
|
|
|
Because you need information about the inheritance tree in order to make sure it works . Such information is not always available , and can be a real bugger to debug if and when MI eventually kicks you in the ass. If you have complete control of all source in a project then there is a case to use it .(I'm ignoring pure virtual base classes used as interfaces, where it is useful and safe ). However if you have complete control , then why not design so that MI is not needed and hence make debugging easier for those who come later ?
|
|
|
|
|
There are a lot of ideosyncracies about MI that can make it difficult to use and maintain. Since I have about 12 years or so of C++, I have used MI quite a bit. However, I only use it for my own personal projects. In situations where I'm consulting or programming for someone else where I don't know who will eventually maintain the code, then I shy away.
By the way, you'll notice that the C# design team intentionally left this feature out (as did the Java team I believe).
Cheers,
Tom Archer
Author, Inside C#
|
|
|
|
|
I don't mean to begin a flame war here, but... Suppose in a high-level design you come with some C tha IS-A A and a C . If you're programming for someone else, would you prefer explaining to her about the standard artifact in Java/C# for dealing with such situation (namely derive from an interface and delegate to a private member)? Is this more intuitive/maintainable than multiple derivation?
Seriously, MI is not such a common pattern, and can lead to obfuscated design, but when it is the appropriate thing to do it can save your life. It goes along with C++ philosophy of treating programmers as grown adults and let them have access to all the tools available, dangerous as they may be.
I know you're a C# guru, so I'd like to know whether there is a pragmatic reason for leaving MI out of this language. Does it make reflection or some other feature harder to implement? That could be a reasonable case against MI.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
>>>
If you're programming for someone else, would you prefer explaining to her about the standard artifact in Java/C# for dealing with such situation (namely derive from an interface and delegate to a private member)?
<<<
Many times when I consult or program for someone, I'll never meet the people that will eventually maintain my code. Therefore, I take it as part of my responsibility to use techniques that are what I feel are standard. It's been my experience that MI is not something that the average programmer fully understands. You'll also note that people such as Bruce Eckel of the C++ standard committee shares this belief and also recommends against using it accept in very rare situations where there are no other options.
>>>
...but when it is the appropriate thing to do it can save your life. <<<
I agree
>>>
It goes along with C++ philosophy of treating programmers as grown adults and let them have access to all the tools available, dangerous as they may be.
<<<
This has nothing to do with treating people as adults and everything to do with the practical realities that part of my responsibility as a programmer is to turn in code that 1) gets the job done and 2) requires as little in terms of maintenance and learning as possible.
>>>
I know you're a C# guru, so I'd like to know whether there is a pragmatic reason for leaving MI out of this language. Does it make reflection or some other feature harder to implement? That could be a reasonable case against MI.
<<<
If you look closely at C# you'll see many situations where the language left out features that are C++ because the risk/reward ration was deemed to high. Case fallthrough is a perfect example of this. Most experienced developers are not going to commit an error with this and love having it at their disposal. However, as Eric Gunnerson explained to me, its not technically needed (as there are other ways to accomplish the same thing) and only serve to get less experienced programmers into trouble. Therefore, while you might very well be a highly-competent programmer who knows MI inside/out, the simple fact is that it gets too many developers into trouble to be worth its risk with its inclusion in the language.
Cheers,
Tom Archer
Author, Inside C#
|
|
|
|
|
I think that IS A is *always* a contentious design decision. BEHAVES LIKE A is (almost) always a more conservative and pragmatic analysis. You should work on the assumption that the latter is the case, and only solidify to an IS-A relationship if you prove, late in the design process that the relationship holds.
Matthew Adams
Development Manager
Digital Healthcare Ltd
|
|
|
|
|
We were having nice simple polls like do you like the new VS.NET UI or how many of you like C# or some such nice simple stuff.
Now it's all templates and multiple inheritance.
And that Georgie Boy is not even to be seen.
Nish
My miniputt high is now 29
I do not think I can improve on that
My temperament won't hold
www.busterboy.org
|
|
|
|
|
Nish [BusterBoy] wrote:
And that Georgie Boy is not even to be seen.
He's probably gloating
I don't mind George, he's a bit narrow minded, but at least he is passionate.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
"I'm thinking of getting married for companionship and so I have someone to cook and clean." - Martin Marvinski, 6/3/2002
|
|
|
|
|
Christian Graus wrote:
but at least he is passionate
True. If anyone can be called passionate, then George sure qualifies...
And he was always alone, facing the multitudes.
Nish
My miniputt high is now 29
I do not think I can improve on that
My temperament won't hold
www.busterboy.org
|
|
|
|
|
|
It was kinda heroic I say
Nish
My miniputt high is now 29
I do not think I can improve on that
My temperament won't hold
www.busterboy.org
|
|
|
|
|
Nish [BusterBoy] wrote:
And he was always alone, facing the multitudes.
Yes, but if I went to /. I would be the same, that doesn't prove anything barring that the greatest zealots are the ones who seek alternative opinions so they can disagree with them and feel the justice of their cause...
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
"I'm thinking of getting married for companionship and so I have someone to cook and clean." - Martin Marvinski, 6/3/2002
|
|
|
|