Monday, May 09, 2005

9. How do I use descriptors as parameters?

The descriptor base classes are described in 11. What is the layout of non-modifiable descriptors? and 12. What is the layout of non-modifiable descriptors?

The base classes provide and implement the constant and modifiable descriptor operations regardless of the actual type of the derived descriptor. For consistency, they should be used as arguments to functions, allowing descriptors to be passed without restricting the caller of the function to using a specific type.

For example, the caller can call the following function with anything derived from TDesC and TDes for the first and second arguments respectively. For example an HBufC and a TBuf<8>, or a TPtr and a TBuf<3>:

void SomeFunction(const TDesC& aReadOnlyDescriptor, TDes& aReadWriteDescriptor);

How do I make a descriptor parameter read-only?

Pass it as a constant reference to a non-modifiable descriptor (const TDesC&). For example:

void SomeFunction(const TDesC& aReadOnlyDescriptor);

This function can still be called with a modifiable descriptor like a TPtr as the argument, because these derive from TDesC (a TPtr is a specialised type of TDes). Inside the function, only the TDesC operations may be performed on the parameter. Its contents will not be changed, even if you have passed in a modifiable, TDes-derived descriptor.

How do I make a descriptor parameter read/write?

Pass it as a non-constant reference to a modifiable descriptor (TDes&). For example:

void SomeFunction(TDes& aReadWriteDescriptor);

You cannot call this function with a non-modifiable descriptor, which makes sense because you don’t want a read only descriptor to be modified.

Inside the function you can both read from and write to the parameter. Remember that the descriptor must already have sufficient space in it for the data to expand into, if necessary. If there isn’t, you’ll get a panic. (Some functions will be coded to check the length of the descriptor before attempting something that may cause a panic and return an overflow error instead. But others will not and the results will be messy).

[ This is one reason why you should always test your code with "boundary conditions" - that is, passing in parameters to functions at the boundary of their acceptable values, and beyond, to check that resulting errors are handled gracefully.]

Can I use other descriptor types as function parameters?

Yes you can, but don’t. For example you could specify your function requiring a parameter passed a TBuf<10>&. But what if the caller has got a TPtrC, or an HBufC, or even a TBuf<11>? This means that they won’t be able to call your function without some extra hassle to fit in with exactly what you have specified. TDes and TDesC are the most general types you can use for your function parameters.

My function uses TDes or TDesC parameters like you say, but my descriptor passing doesn’t work. Why not?

Oh how much pain has this one caused? Missing out that little & symbol makes all the difference. Your parameter types must be references, not values, ie const TDesC& or TDes&.

The base classes TDesC and TDes contain no string data. If you pass them by value rather than by reference, you are using static binding, which means that polymorphism won’t work, and you'll end up with a data-free base class object. It will all compile OK, but nothing works.

Never attempt to instantiate or work directly with objects of the base classes TDesC or TDes, as Tip 1 advises. They are effectively abstract classes. There is rarely, if ever, a valid reason for instantiating them rather than an object of their deriving classes (TBufC, TBuf, TPtrC, TPtr, HBufC or RBuf).

Note that the the TDesC and TDesC base classes are referred to as 'abstract' by Symbian OS documentation.

But they're not abstract in typical C++ sense. Descriptors do not have pure virtual functions. In fact, descriptors have no virtual functions at all, despite the use of C++ inheritance. With no virtual functions, there is no need for a vtable pointer (4-byte overhead) for each object instantiated. This keeps memory usage to a minimum.

TDesC is non modifiable version of descriptor,if that is the case, then why do we use const while passing parameter in function.

For eg
void FOO(const TDesC&);
Good question. There are two issues going on here.

(1) Firstly we have the meaning of C in descriptors such as TBufC, HBufC and TPtrC. It means that the descriptor is non-modifiable in the sense that it derives directly from TDesC, and has no modifiable functionality. It's a guarantee of constness from the point of view of that Symbian OS class.

However, as I've shown for HBufC ( you can still modify a non-modifiable descriptor by creating a modifiable pointer (TPtr) over the non-modifiable descriptor's data.

For example (sorry about the formatting):

TBufC<12> myNonModifiableBuf(_L("Hello World"));

TPtr myModifiablePtr(myNonModifiableBuf.Des());

Then you can call modifiable methods on myModifiablePtr, and effectively change the contents of myNonModifiableBuf.

(2) Secondly we have the concept of C++ constness. This is a guarantee that the C++ object is non-modifiable (rather than just the guarantee from a Symbian OS)

This will now not compile:

const TBufC<12> myNonModifiableBuf(_L("Hello World"));

TPtr myModifiablePtr(myNonModifiableBuf.Des());

So passing const TDesC& as a parameter means that not only is the parameter conceptually constant (as in the Symbian OS class used) but it is enforced as constant by C++.
How to use a jstring value to initialize a TDesc. The jstring holds a filename which is to be passed to a Symbian class as a TDesc parameter. Hardcoding works but if this is obtained via a java pgm how to go abt it.
Sorry, this is a bit late comment. Anyway...

What if there was a function that would eventually delete and set to NULL the HBufC* I'm passing to it? You can't (shouldn't) set a reference to NULL. What would be the correct way to do this? I found this kind of function from the code I'm working with and as a noob I'm not so comfortable with my solution after reading this FAQ.
I'm not sure I understand the comment in the context of this FAQ.

If you're passing an HBufC* as a reference, given this text, I assume you're de-referencing it to pass as a TDesC& paramter - which can't be deleted and set to NULL. Well, it can, but only if the function knows that you're passing a de-referenced HBufC* - and it shouldn't.

It's not generally good practice to write functions that take parameters as HBufC*& - I have seen this kind of code, but far better that the function returns HBufC* and transfers ownership at that point.

Perhaps you could clarify and post a code snippet to help me understand?
The function is like this:
void foo(HBufC* a) {
delete a;
a = NULL;

And it is used like this:
HBufC* bar;

So, eventually the foo function deletes the contents of bar and sets it to NULL.

Is there a "more correct" solution available?

Thank you!
Is it necessary to have foo delete bar? Does it have to know that it's dealing with an HBufC at all? If the answer to both is "No" then I'd rework foo to take TDesC& and allow the function that created bar to also destroy it.

If the answer is "Yes", can you re-design?
Yes, it was necessary to destroy it but I thought it's better to destroy in the same context it was created. That caused me some extra work but now it works as intended and is more elegant.
What if i write a function that takes Foo(TDesC &aParam)

How can i check within Foo() that aParam is allocated?
Catch the wow gold star that holds your gold in wow destiny,cheap wow gold the one that forever maplestory money twinkles within your heart. Take advantage of precious opportunities while they still sparkle before you. Always believe that your buy maplestory mesos ultimate goal is attainable cheap mesos as long as you commit yourself to it.maple money Though barriers may sometimes stand in the way of your dreams, remember that your destiny is hiding behind gold kaufen Accept the fact that not everyone is going to approve of the choices Maple Story Accounts you've made. Have faith in your gold farmen Catch the star that maple story money twinkles in your heart and it will lead you to your destiny's path. Follow that pathway and uncover the sweet sunrises that await you. Take pride in your accomplishments, as they are stepping stones to your dreams. Understand that you may make mistakes, powerlevelbut don't let them discourage mesos Value your capabilities and talents for they are what make you truly unique. The greatest gifts in life are not purchased, but acquired through hard work and determination.maplestory mesos Find the star that twinkles in your heart?for you alone maplestory powerleveling are capable of making your brightest dreams come true
Youth is not wow gold a time of life;world of warcraft gold it is a state of mind; cheap wow gold it is not a Maple Story Accounts matter of rosy cheeks, red lips and supple knees;mesos it is a matter of the will, a quality of the imagination,wow gold kaufen a vigor of the emotions; it is the freshness wow geld of the deep springs of life.maple story mesos Youth means a tempera-mental predominance of courage over timidity, of the appetite for adventure over the love of ease. This often exists in a man of 60 more than a boy of gold farmen Nobody grows old merely by a number of years.maple story money We grow old by deserting our mesos Years may wrinkle the skin, but to give up enthusiasm wrinkles the soul. Worry, fear, self-distrust bows the heart and turns the spring back to dust. Whether 60 or 16, there is in every human being’wow powerleveling s heart the lure of wonder, the unfailing childlike appetite of what’s maple story money next and the joy of the game of living.powerlevel In the center of your heart and my heart there is a wireless station: so long as it receives messages maplestory powerleveling of beauty, hope, cheer,world of warcraft power leveling courage and power from men and from the Infinite
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?

WWW Descriptors FAQ