Is this acceptable?

Started by
10 comments, last by thedo 22 years, 5 months ago
for a personal project I am creating a series of components for C++ Builder which manipulate D3D8. Now then..... Is this generally seen as acceptable? class D3D { private: LPDIRECT3DDEVICE device; : : public: LPDIRECT3DDEVICE GetDevice(); : : }; and then passing that Device to a model class to render I am a bit worried about the GetDevice() because a: it exposes the main part of the class to the open world. b: means having many copies of the Device object in the models (could be static I know but thats for later) c: makes code unreadable i.e. Model->initialize(Scene->GetDevice()); - we shouldn''t put the programmer through this should we? Ideas and notes would be welcomed Neil
WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
Advertisement
First of all I'm sure somebody is going to have a much better answer to this that I have, but I'll explain it as I've been taught:

Having an accessor method like GetDevice() is seen as a safer method of exposing the class variables because it is impossible to accidently change the value of device through it (i.e. you can't do D3DObject->GetDevice() = new LPDIRECT3DDEVICE(); ) whereas you could do D3DObject.device = new LPDIRECT3DDEVICE();. This isn't a great example, but imagine you had two LPDIRECT3DDEVICE's and wanted to check if they were the same. It would be very easy to do:
if (D3DObject1.device = D3DObject2.device)
but this would make the two devices equal instead of testing them. Using accessor methods avoids these potential problems.

EDIT: stupid smilies!

Edited by - Enigma on November 19, 2001 10:56:23 AM
BUT....
What if someone says
LPDIRECT3DDEVICE dev=Scene->GetDevice();

Firstly I dont want the component user to have access to change environment settings - this could mess things up in the app if the setting isn''t supported (basic example - if texturing is set to multitexture on a card with only one texture unit (OK it''s a bad example as most cards do have support for multitexture)).

Also i see it as bad practice to HAVE to call a method like this
Model->Init(Scene->GetDevice());

The idea is that the user shouldn''t know/care what is doing the drawing (therefore we cannot assume familiarity with D3D) and the components must be easy to use (if only for my own sake).

Would ''friend''s work? I''ve read about them but the syntax isn''t obvious to me. Any help.

Cheers

Neil
WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
If you don''t want the component user to be able to change things in the LPDIRECT3DDEVICE, then just make the accessor method return a copy of it (if this is possible, I don''t actually know what an LPDIRECT3DDEVICE is!), that way the component user can read any information they need but any changes will have no effect on the D3D class.

I agree that

Model->Init(Scene->GetDevice());

is a bit messy, but it''s not that much worse than

Model->Init(Scene.device);

and if you dereferenced the pointers you could write it as:

Model.Init(Scene.getDevice());

Or, if you wanted to be a bit fancy, find a character you don''t use (~ maybe) and #define this to ->. Now you can write:

Model~Init(Scene~getDevice());

Or as another alternative, simply make your Init method get the device itself:
Model->Init(Scene);void Model::Init(SceneThing* Scene){   LPDIRECT3DDEVICE device = Scene->getDevice();   DoStuff();} 

I would suggest that any changes that can be made to the LPDIRECT3DDEVICE should be forced to be made through the D3D class, i.e.

D3DObject.setAttribute#1(value)

This will entirely hide the LPDIRECT3DDEVICE from the rest of the program.
i am pretty far from knowing much about Direct3D, but i think that LPDIRECT3DDEVICE is a pointer (it''s that hungarian notation or whatever... LP = long pointer). so, you are just returning (or passing around, or copying) a pointer.
i''m fairly new to c++ also, but they might be able to mess with the device''s internal members because of this (device->messMeUp(void)). on this one, though, i''m not sure, so hopefully someone who is knowledgable will tell me to shut up and give you a complete answer.

--- krez (krezisback@aol.com)
--- krez ([email="krez_AT_optonline_DOT_net"]krez_AT_optonline_DOT_net[/email])
Thanx for the input. For those not in the know
an LPDIRECT3DDEVICE is a pointer to a Direct3DDevice object.

If i was to pass back a de-referenced instance of the object it could be incredibly slow - also I don''t think that the Model class could use it then as it''s NOT the original object (it''s just a copy of it). I''m not going to make Device public (the thought never crossed my mind (honest)) but passing back a pointer to the instance of that object just seems ''dangerous'' and produces unreadble code. I have a lttle knowledge of friends (where a stated object has access to another objects private methods and variables), but i don''t actually knw how to use them.

the code I have seen looks a little like this

class D3D
{
private:
friend LPDIRECT3DDEVICE Device;
:
:
public:
:
:
};

BUT how does the compiler know what the LPDIRECT3DDEVICE is the friend of?

Cheers again

and thanks for the views even though i''m not quite there yet you have at least got rid of some possibilities (and made me look up a couple of things - something we should all do more before asking silly questions)

Neil

WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
you can declare a function outside the class with the friend keyword:
    class FooClass  {  private:    int someVar, otherVar;    :    :  public:    friend int DaFunction(FooClass);    :    :  };::int DaFunction(FooClass Bah)  {  return Bah.someVar;  };  you can also make a class a friend of another class, so the latter can access the private stuff in the former:      class FooClass;class BahClass  {  private:    int thisVar, thatVar;  public:    int UseMyFriend(FooClass);  };int BahClass::UseMyFriend(FooClass Foo)  {  return Foo.someVar;  };class FooClass  {  private:    int someVar, otherVar;  public:    friend class BahClass;  };    

so basically, you do not declare the LPDIRECT3DDEVICE as a friend, you declare the function (or class) that can use it as a friend (in the public part of the class).

--- krez (krezisback@aol.com)

Edited by - krez on November 19, 2001 7:16:42 PM
--- krez ([email="krez_AT_optonline_DOT_net"]krez_AT_optonline_DOT_net[/email])
Create a singleton class, so there''s only one copy of the LPDIRECT3DDEVICE hanging around. You should also consider redesigning your class framework if your model requires a pointer to the device for its initialization. Encapsulate in entirety as many objects as possible so that they do not depend on each other unless absolutely necessary.
Cheers Krez - I understand it now (at least what you wrote).
Just wanted to say thanks - i''m going to do it this afternoon

Cheers

Neil
WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
Don''t forget to increase the reference count of the device pointer when you are passing it around like that and then decrease it when you''re done.

"You are too useless. And now I must beat you." - English subtitle in a Honk Kong Movie.

This topic is closed to new replies.

Advertisement