const CString& CString::operator=(LPCTSTR lpsz)
{
/* ### */
if (lpsz != NULL && HIWORD(lpsz) == NULL)
{
UINT nID = LOWORD((DWORD)lpsz);
if (!LoadString(nID))
TRACE1("Warning: implicit LoadString(%u) failed\n", nID);
return *this;
}
/* ### */
ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
AssignCopy(SafeStrlen(lpsz), lpsz);
return *this;
}
thanks microsoft!
Passing a resource ID is supported in the CString ctor, but apparently not
in the operator =. How were you planning to use this capability? Like
this?
CString str;
str = MAKEINTRESOURCE(IDC_MY_STRING);
This is highly unusual. This code is more readable and supported in the
standard CString:
CString str;
str = CString(MAKEINTRESOURCE(IDC_MY_STRING));
-- David
guess you have...
class foo{
public:
inline void TestSet(LPCTSTR sz) {m_scTest = sz;};
private:
CString m_scTest;
};
Note that this is already supported in the constructor.
joe
Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
I would say TestSet is buggy. Prototyping it to take an LPCTSTR and
expecting it to work with a resource ID is not something as a user of your
class I would expect. It doesn't expose any MFC stuff, and it's only
CString that can take a resource ID in place of an LPCTSTR in some cases
(the ctor). Why don't you add another method:
inline void TestSet(UINT resId) { m_scTest =
CString(MAKEINTRESOURCE(resId); }
-- David
> I'm curious why you think you have to support this in the assignment operator. Note you
> could have put this code in your TestSet method without having to muck with the CString
> definition.
> joe
>
>
shure, but i have *a real lot* of those "TestSet"-methods in my
code...
> So who is 'they' and what is 'nuts' related to here? You seem to have extended CString
> assignment by modifyting the CString source code in MFC, which actually seems a bit
> 'nuts' to me.
of course not! i just noticed something missing in there.
> What's the question?
given the fact that CString is a really small piece of code ... how
could someone support
IntResources in the ctor and not in the op= !?
Well said.
AliR.
#define ResStr(x) CString(((UINT_PTR)(x)) <= 0xFFFF ? MAKEINTRESOURCE(x) : (x))
or
__inline CString MakeStr(UINT x) { return CString(MAKEINTRESOURCE(x)); }
__inline CString MakeStr(LPCTSTR s) {
return ((UINT_PTR)s) < 0xFFFF ? CString(MAKEINTRESOURCE((UINT) s)) : s; }
and the problem goes away.
joe
class foo{
public:
inline void TestSet(LPCTSTR sz) : m_scTest(sz) {};
private:
CString m_scTest;
};
It is better to initialize everything you can outside
the body of the constructor anyway.
--
Mihai Nita [Microsoft MVP, Visual C++]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email
> class foo{
> public:
> inline void TestSet(LPCTSTR sz) : m_scTest(sz) {};
> private:
> CString m_scTest;
> };
>
> It is better to initialize everything you can outside
> the body of the constructor anyway.
TestSet is not a constructor... it is just a setter...
Or am I missing something here?
Thanks,
Giovanni
> of course not! i just noticed something missing in there.
It's not missing. It's implemented in the LoadString() method.
> given the fact that CString is a really small piece of code ... how
> could someone support
> IntResources in the ctor and not in the op= !?
There's nothing small about CString anymore. This functionality is
there--it's just not implemented the way you appear to think it should be.
--
Jonathan Wood
SoftCircuits Programming
http://www.softcircuits.com
http://www.softcircuits.com/blog/
My solution...
//-----------------------------------------------------------------------------
class CQString : public CString
{
public:
// overloaded contructors refer to baseclass
inline CQString() {};
inline CQString(const CString& stringSrc) : CString(stringSrc) {};
inline CQString(LPCTSTR lpsz) : CString(lpsz) {};
#ifdef _UNICODE
inline CQString(LPCSTR lpsz) : CString(lpsz) {};
#else
inline CQString(LPCWSTR lpsz) : CString(lpsz) {};
#endif
// additional constructor for resource-id's
inline CQString(UINT nRscID) {LoadString(nRscID);};
// destructor does nothing
virtual inline ~CQString() {};
// the only real overload, we need to check for ResourceID
const CQString& operator=(LPCTSTR lpsz);
};
//-----------------------------------------------------------------------------
// the only real overload, we need to check for ResourceID
const CQString& CQString::operator=(LPCTSTR lpsz)
{
if (lpsz != NULL && HIWORD(lpsz) == NULL)
{
UINT nID = LOWORD((DWORD)lpsz);
if (!LoadString(nID))
TRACE1("Warning: implicit LoadString(%u) failed\n", nID);
return *this;
}
> // the only real overload, we need to check for ResourceID
> const CQString& operator=(UINT ResourceID);
That way you have yours that takes a resource ID, and CString has his own
that takes a LPCTSTR.
And also you won't have to cast your resource ID into a LPCTSTR when you
want to use the assignment operator.
Ali
".rhavin grobert" <cl...@yahoo.de> wrote in message
news:741e8083-bb60-485d...@s9g2000prg.googlegroups.com...
> Why didn't you just make your operator overload take a UINT?
>
> That way you have yours that takes a resource ID, and CString has his own
> that takes a LPCTSTR.
>
> And also you won't have to cast your resource ID into a LPCTSTR when you
> want to use the assignment operator.
It just to be consistent with the constructors.
>
> Ali
>
>
Its a point! i just added ....
inline const CQString& operator=(UINT nRscID)
{LoadString(nRscID); return *this;};
>On 4 Feb., 18:13, ".rhavin grobert" <cl...@yahoo.de> wrote:
>> that leads me to the question: can i derive from CString if the only
>> thing i do is overload the operator=()...
>
>My solution...
>
>
>//-----------------------------------------------------------------------------
>class CQString : public CString
>{
>public:
> // overloaded contructors refer to baseclass
> inline CQString() {};
> inline CQString(const CString& stringSrc) : CString(stringSrc) {};
> inline CQString(LPCTSTR lpsz) : CString(lpsz) {};
>
> #ifdef _UNICODE
> inline CQString(LPCSTR lpsz) : CString(lpsz) {};
> #else
> inline CQString(LPCWSTR lpsz) : CString(lpsz) {};
> #endif
>
> // additional constructor for resource-id's
> inline CQString(UINT nRscID) {LoadString(nRscID);};
>
> // destructor does nothing
> virtual inline ~CQString() {};
>
> // the only real overload, we need to check for ResourceID
> const CQString& operator=(LPCTSTR lpsz);
>};
There are several problems with this:
1. The following behave very differently:
CString x('a');
CQString x('a');
The first one does what is expected for a string class; it constructs a
string equal to 'a'. The second one does something bizarre.
2. Your comment notwithstanding, you're not overloading operator=. In fact,
your operator= is the only one your class has. It accepts CStrings due to
CString's conversion operator, and assignment to a CQString will never
benefit from CString's reference-counting. You would work around this
problem with a using-declaration, but the return types would remain
CString&, which is wrong. The proper way is to add the CString operator=
signatures by hand, including the copy-assignment operator, changing the
return type to CQString&.
3. The semicolons following the end-brackets of function definitions are
not necessary and should not be used.
4. CString has no virtual functions, and it is bad practice to derive
publicly from it. The traditional objection is that is undefined to delete
a CQString through a pointer to its CString base. Perhaps more importantly,
you will probably start writing interfaces in terms of CQString. Passing a
CString where a CQString is required makes a copy of the CString; this is
inefficient (though mitigated by reference-counting) for CQString const
reference parameters and is incompatible with CQString non-const reference
parameters. Furthermore, suppose you mix your code with similar code that
uses CXString. There will probably be some functions f(CXString), and you
cannot pass your CQStrings to them.
5. There's no legitimate reason for CQString to exist. The CString class
already provides the LoadString function and a ctor that takes a resource
ID cast to a string, and they are what you should use.
--
Doug Harrison
Visual C++ MVP
Sorry, my bad. I missed something :-)
Somehow I did not pay attention to the name of the class.
No problem! :)
C++ is a complex language and evolving too, so I thought that might be a new
C++0x feature or something from Alexandrescu's advanced book on C++.
Giovanni
Now you are making fun of me :-)
Well deserved though.
No.
I don't make fun of anybody.
Giovanni