Archived

This topic is now archived and is closed to further replies.

noxa

Ambigous operators? uhm...

Recommended Posts

Hello, I''m writing a class and have run into another (yes, another) little block: MSVC is screaming about my operators being ambigous! My class is a string wrapper, and an example of where this occurs is when I try to do a OutputDebugString() command... (csTemp = my class filled with "world", my class is called CStr) ex: OutputDebugString("Hello " + csTemp + "!"); this gives me an error, I have to do this: OutputDebugString(CStr("Hello") + csTemp + CStr("!")); This is a pain, how can I fix this? I believe the problem lies within the root of my code, where if have my operators, some of the ones I have are the following: + (char*) + (const char*) + (CStr) + (int) + (long) + (char) + (float) What I think is happening is that it is getting my CStr operator is getting confused with the const char* operator, as my class also contains operators for exporting to that type. If you understand me, you see how confusing this is! My class needs to provide these operators, which is why I can''t remove them... Any help would be greatly appreciated! ~noxa~ Ben Vanik

Share this post


Link to post
Share on other sites
The problem is that you are using the unary plus operator( the one that is makes and object positive) instead of the binary operator( the one that adds to objects together ). You need to change the operators to something like this:

friend CStr operator+ ( CStr &right, CStr &left );
friend CStr operator+ ( CStr &right, const char *left );
friend CStr operator+ ( const char *right, CStr &left );
friend CStr operator+ ( CStr &right, char *left );
friend CStr operator+ ( char *left, CStr &right );
friend CStr operator+ ( CStr &right, char left );
friend CStr operator+ ( char left, CStr &right );

This way you have all senarios accounted for. You can have the literal string before or after the CStr object and the string concatenation will still work.

Edited by - Ranok on 4/2/00 7:27:23 PM

Share this post


Link to post
Share on other sites
In the end, I had to choose between a constructor that took a char*, or an operator converting to a char*, as with both of them there were numerous situations where it couldn''t tell which was was preferred. Although I haven''t tried all the different functions as Ranok described below, largely because reputable sources states that this dilemma is a common one and not easy to get around.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Instead of defining all possible scenarios, it suffices to have constructor accepting the possible types you want to use, and define one operator that works on references to CStr. The compiler will implicitly convert to the CStr class type by using the constructor, and use the + operator.

All this has to do with the conversion rules that C++ uses. Any recent and good C++ book should have explanations of this issue (Lippman''s ''C++ primer'' has it for sure).

Erik

Share this post


Link to post
Share on other sites
As long as you define CStr::operator const char*() and CStr::CStr(const char*), you don''t need to define separate operators (+, -, *, /, etc.) for all the char*. CStr::CStr(const char*) acts like a conversion operator to convert any char* into a CStr object. Consider the following:


class CStr
{
public:
CStr() { m_pData = NULL; }
CStr(const char*);
CStr(const CStr&);

operator const char*();

CStr operator +(CStr);

CStr& operator =(CStr&);

protected:
char* m_pData;
};

CStr::CStr(const char* pStringData) // automatic conversion to CStr
{
m_pData = pStringData;
}

CStr::CStr(const CStr& szOtherString)
{
// ...create a new array and copy the data...
}

CStr::operator const char*()
{
return m_pData; // automatic conversion to const char*
}

CStr CStr::operator +(CStr szOtherString)
{
// ...use strcat or whatever you were using...
}

CStr& CStr::operator =(CStr& szOtherString)
{
// ...do the same thing as CStr::CStr(CStr),
// but we need to delete the existing buffer first...
}


// source code example
// make two strings
CStr szString1("Hello");
CStr szString2("World!");

// make "Hello World!" phrase
CStr szString3 = szString1 + " " + szString2;



The previous code probably will not compile properly because some things are obviously missing. However, I think you get the basic point. Let''s take a look at the code example, and what''s really happening. First, the compiler constructs two CStr objects from const char*''s. When we go to the third statement, here''s what happens:


    Step 1 - The compiler constructs an empty CStr object using "CStr::CStr()".

    Step 2 - Then, it starts at the rightmost part of the expression and works backward, to the left. First, it looks for a "const char* operator +(const char*, CStr)", and can''t find one.

    Step 3 - Second, it tries to find a conversion operator to convert the rightmost CStr to a const char*, which it finds the conversion operator, "operator const char*()". However, it cannot find "const char* operator +(const char*, const char*)". So, it continues searching...

    Step 4 - Third, it tries to convert the left argument, in this case " ", which is a const char*, to a CStr, because it sees "CStr CStr::operator +(CStr)". It uses the constructor "CStr::CStr(const char*)" to make a temporary CStr object, which it can then use to add the strings together and return a CStr. Then, it continues to the next expression, which is szString1 + " ".

    Step 5 - It sees the "CStr CStr::operator +(CStr)" and uses it. Now, it results in the string "Hello World!"

    Step 6 - Finally, it constructs an empty CStr object and uses the "CStr::CStr(const char*)" to construct a temporary CStr object, which it then uses in the call to CStr& CStr::operator =(CStr&).


Whew! Like Erik said, you need a book on the subject to fully understand it.




- null_pointer
Sabre Multimedia

Share this post


Link to post
Share on other sites
quote:
Original post by null_pointer

As long as you define CStr::operator const char*() and CStr::CStr(const char*), you don''t need to define separate operators (+, -, *, /, etc.) for all the char*.


Surely this leaves you with the same problem: when the compiler sees

CStr str1;
char* str2;
return str1 + str2;

It doesn''t know whether to convert str1 to a char*, or to convert str2 to a CStr, since both conversions are available?

Share this post


Link to post
Share on other sites