|
Prev: MFC - _beginthreadex
Next: typedef vs inheritance
From: Carmen Sei on 16 Apr 2008 20:43 Is there any way to return either NULL or a SYSTEMTIME object? will it work in C++? as in Java, one can return either NULL or an object, does C++ has something similar? Is the following code OK for C++? ================= SYSTEMTIME Table::Get(char* FieldName) { _variant_t vtValue; vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue(); if (vtValue.vt == VT_NULL) { return NULL; } SYSTEMTIME m_st; VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_st); return m_st; }
From: Doug Harrison [MVP] on 16 Apr 2008 21:21 On Wed, 16 Apr 2008 17:43:45 -0700, Carmen Sei <fatwallet951(a)yahoo.com> wrote: >Is there any way to return either NULL or a SYSTEMTIME object? will >it work in C++? > >as in Java, one can return either NULL or an object, does C++ has >something similar? In Java, you're returning a reference to an object or NULL. The corresponding thing in C++ would be to return a pointer or NULL. >Is the following code OK for C++? >================= > >SYSTEMTIME Table::Get(char* FieldName) >{ > _variant_t vtValue; > vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue(); > > if (vtValue.vt == VT_NULL) { > return NULL; > } > SYSTEMTIME m_st; The "m_" prefix signifies "member variable" and shouldn't be used to name local variables. > VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_st); > return m_st; >} No, SYSTEMTIME is a struct, not a pointer, and to return a SYSTEMTIME is to return the entire struct by value. As C++ is not garbage-collected, you really can't return a pointer here. (You could make m_st static and return a pointer, but then you're no longer thread-safe, and each call to Get destroys the previous result. You could instead create it dynamically, but then the caller would have to assume ownership and delete the object. Neither are recommended.) What you can do is change the function as follows: bool Table::Get(char* FieldName, SYSTEMTIME& st) { _variant_t vtValue; vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue(); if (vtValue.vt == VT_NULL) { return false; } VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &st); return true; } -- Doug Harrison Visual C++ MVP
From: Carmen Sei on 17 Apr 2008 01:03 Then C++ programmer most of time will pass in a reference (SYSTEMTIME& st) most of time for passing value back to caller function? bool Table::Get(char* FieldName, SYSTEMTIME& st) { _variant_t vtValue; vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue(); if (vtValue.vt == VT_NULL) { return false; } VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &st); return true; } ===================== another way to do this is - SYSTEMTIME* Table::Get(char* FieldName) ===================== but the following is better way for returning value back to caller function and most programmer do this way?? bool Table::Get(char* FieldName, SYSTEMTIME& st) >No, SYSTEMTIME is a struct, not a pointer, and to return a SYSTEMTIME is to >return the entire struct by value. As C++ is not garbage-collected, you >really can't return a pointer here.
From: dertopper on 17 Apr 2008 04:01 Carmen Sei wrote: > Is there any way to return either NULL or a SYSTEMTIME object? will > it work in C++? > > as in Java, one can return either NULL or an object, does C++ has > something similar? > > Is the following code OK for C++? > ================= > > SYSTEMTIME Table::Get(char* FieldName) > { > _variant_t vtValue; > vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue(); > > if (vtValue.vt == VT_NULL) { > return NULL; > } > SYSTEMTIME m_st; > VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_st); > return m_st; > } Have you tried to compile it? C++ distinguishes between objects and pointers to objects (in contrast to Java, where everything is a pointer to an object). Thus you can specify in C++ that a function will always return a valid object (something that cannot be NULL, so you don't have to write code to check that the return value is actually non-NULL) by making the return type an object: SYSTEMTIME Table::Get(char* FieldName) This will always return a valid SYSTEMTIME (unless it throws an exception). The semantics you want to express is a bit different. What you actually want to specify is a method that returns a valid SYSTEMTIME when a certain condition is met, or a value that indicates that no meaningful SYSTEMTIME could be returned because the condition is _not_ met (in your case the condition is that the data base contains an entry that can be coerced into a SYSTEMTIME in the specified field). You have two alternatives to design this: (A) Use a special DATETIME value that indicates that you could not retrieve such a value from the data base (for example you could use the time where all members are set to zero). (B) Return a pointer to a DATETIME, which will be NULL if the condition isn't met. In this case the called method will have to allocate memory on the heap, so the calling entity would have to ensure that this memory is properly released. The standard way of doing this is making the return type an auto_ptr: std::autoptr<SYSTEMTIME> Table::Get(char* FieldName); The auto_ptr will ensure that the memory is properly released, and above all this is the exception-safe way of returning new'ed objects (see Herb Sutter's "Exceptional C++" for a better description). Both alternatives are equally well suited to do what you want, alternative B is a bit closer to the way a Java programmer would handle such a case. Regards, Stuart
From: Ulrich Eckhardt on 17 Apr 2008 03:54
Note up front: this has nothing to do with the MFC, dropping mpvm from the list of groups. Carmen Sei wrote: > Is there any way to return either NULL or a SYSTEMTIME object? will > it work in C++? > > as in Java, one can return either NULL or an object, does C++ has > something similar? Doug already pointed out the differences to the Java object model, and that the closest in C++ is a pointer. > Is the following code OK for C++? > ================= > > SYSTEMTIME Table::Get(char* FieldName) > { > _variant_t vtValue; > vtValue = m_Rec->Fields->GetItem(FieldName)->GetValue(); > > if (vtValue.vt == VT_NULL) { > return NULL; > } > SYSTEMTIME m_st; > VariantTimeToSystemTimeWithMilliseconds (vtValue.date, &m_st); > return m_st; > } No: 1. In what way is 'FieldName' modified? If it isn't, make it 'const', because otherwise the function implies that it is. Other than that, in C++ you should use a string class like std::string or CString. 2. Use initialisation instead of assignment, i.e. merge the two first line of this function. Further, it helps actually making such values constant, so you don't accidentally modify them later on. 3. I'm pretty sure that it doesn't compile, so it obviously isn't correct. ;) Doug mentioned some ways to solve this, but I'd like to add two of them: 1. If you can't return something from a function, just like in Java, you can throw an exception. I would for example use std::runtime_error from <stdexcept> which allows carrying a std::string as additional info. In some cases it would even make sense to derive an own exception type. This avoids having to check each and every returnvalue when the only thing you can do is to forward the error. 2. If you need to pass an object to the caller, and the caller is supposed to assume ownership of it, use std::auto_ptr. Its semantics are a bit confusing at first, but they come very handy in practice. Uli -- C++ FAQ: http://parashift.com/c++-faq-lite Sator Laser GmbH Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932 |