CNullDriver

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

And you will see that they all have a function body with driverdependent code ...
Exactly. Each of the derived drivers implement behavior that is specific to that driver. The OpenGL driver makes lots of glWhateverFunction type calls, and the D3D drivers make pID3DDevice->WhateverFunction calls. Obviously those functions could not be put into the base class.

As mentioned before the functionality that is in the null driver is common to all of the drivers. Some methods are unnecessarily duplicated, but for the most part the null driver class does provides shared functionality.

All of the external mage loader and image writer functionality is there, the texture cache management, image loading, fps counting, light management, material renderer management, material serialization...

As an example of why it is necessary, the function draw2DPolygon() is not implemented in any derived driver. Neither are draw3DBox(), draw3DTriangle(), makeNormalMapTexture() and createImageFromFile().

So, in summary... The dependency on null driver is there because it is a repository for code that is common to all of the currently implemented drivers. Because the derived drivers [OpenGLDriver, D3D9Driver, ...] inherit from the null driver, they don't need to reimplement those shared methods. You can reimplement those methods in the derived class, but it is not required.

Sometimes methods are reimplemented in the derived class because the derived class can sometime do things better than the base class implementation, or the derived class needs to do something a little differently. The null driver implementation of draw2DLine() does nothing. If the derived class didn't reimplement it, then nothing would be drawn. Drawing a line is driver specific, so it couldn't be written in the null driver class.

Why does all of this matter to you anyways? From a coders perspective, the derived driver looks just the same if it implements all of the functionality itself or if the functionality is inherited. From your perspective, you get a pointer to an IVideoDriver and that is all you really need to worry about.

This is about as simply as I can explain it.
Cppuser
Posts: 12
Joined: Thu Sep 28, 2006 8:38 pm

Post by Cppuser »

Thx vitek,

my problem was that i only saw the empty methods in CNullDriver last night.
That's why i didn't understand what everybody is trying to explain me.
But after a detailed look in he morning 've seen that i was blind. ;)

And you confirmed my question in my last posting ...
vitek wrote: Why does all of this matter to you anyways? From a coders perspective, the derived driver looks just the same if it implements all of the functionality itself or if the functionality is inherited. From your perspective, you get a pointer to an IVideoDriver and that is all you really need to worry about.
Coding without knowing what is going on is not a very good base for a coder. And if a coder doesn't interesting in things behind he is not really knowing what he is doing.
IMHO If coders don't know what exactly is going on they got the wrong job.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Coding without knowing what is going on is not a very good base for a coder.
And posting without knowing what you're posting about is not a good base for a poster... :)

I can agree with what you are saying to a certain extent. Often there are implementation details. They only matter to the people dealing with the implementation. Unless you are wanting to get your hands dirty in the driver implementation, you don't need to look at or even understand the details. All you need to know is the published interface and how to use a debugger.

Travis
EmmanuelD
Posts: 25
Joined: Thu Aug 24, 2006 8:34 am
Location: Right in front of Dagoth Ur
Contact:

Post by EmmanuelD »

Saturn wrote:The reason is code reuse simply. CNullDriver does the generic part of the implementation of the IVideoDriver interface. Else this interface had to be implemented inside a header, which were acceptable for smaller functions, but not for 40k big source. Other alternative were to implement those functions in each of the drivers, but such code duplication is bad for obvious reasons.
Well, from a design point of view, implementation driven inheritance in still a bad idea. To avoid code duplication, one could write a common component which is instantiated in all the classes that need it. Something along the line of

Code: Select all

class CDriverImpl
{
 // blah
};

class CNullDriver
{
  CDriverImpl DriverImpl;
};

class CD3D9Driver
{
  CDriverImpl DriverImpl;
};

class COpenGLDriver
{
  CDriverImpl DriverImpl;
};
And so on. 
This is far easier to manage (note: this is not the pimpl/bridge pattern, although it looks like it; this is simply a basic composition. The bridge pattern allow the private implementation to change).

@Cppuser: you have to read about inheritance and function overloading. If a class B inherit a class A and if the method f in A is virtual, you can redefine this method in B (I think you know this). The method f in B is allowed to call the method f in A, using this code:

Code: Select all

void B::f()
{
   A::f(); // calling the superclass f() method
}
So while you still have to write B::f() (but you are not required to do so), you can reuse the code of A::f() rather easily.

HTH,
-- Emmanuel D.
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post by Saturn »

While I agree that Inheritance is often overused and composition can be more sensible in some places, I still think in this context implementation inheritence is ok and even superior.

Because what about the parts that are not covered by the generic CDriverImpl, because they a API specific? Do you implement them directly in the driver or do you inherit from the implementation class or do you create another API specific parallel implementation? All of these solutions have other trade-offs one has to deal with and without having this invesitgated, I doubt they are simpler to handle than how it is done now.

Nevertheless one problem with mixed implementation/virtual inheritence is that one can have virtual spaghetti like in good old basic(goto) times, simply because the implementation is cluttered over the whole hierarchy. Though with a two-classes-hierarchy this is managable...
Post Reply