473,382 Members | 1,407 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

Type conversion function for user type again.

I got a good answer here I have still confusing part.

I have two very simple classes

class DRect
{
private :
double x0, y0, x1, y1;
public :
DRect(double a, double b, double c, double d) : x0(a), y0(b),
x1(c), y1(d) {}
void Union(const DRect* p)
{
x0 = MIN(x0, p->x0);
y0 = MIN(y0, p->y0);
x1 = MAX(x1, p->x1);
y1 = MAX(y1, p->y1);
}
};

class IRect
{
private :
int x0, y0, x1, y1;
public :
IRect(int a, int b, int c, int d) : x0(a), y0(b), x1(c), y1(d)
{}
operator DRect() const
{
return DRect(x0, y0, x1, y1);
}
operator DRect*() const
{
return &DRect(x0, y0, x1, y1);
}
};

and the execution code here.

void main()
{
DRect d(5.3, 5.3, 15.6, 15.6);
IRect i(10, 10, 100, 100);

/* 1. No problem with compiling this code. */
d.Union(&(static_cast<DRect>(i)));

/* 2. It isn't compiled. */
d.Union(&i);
}

My question is

1. The second execution code 'd.Union(&i)' is quite resonable. People
usually do something like this.

DRect d1(2.3, 5.3, 98.2, 34.2);
DRect d2(5.2, 4.2, 99.1, 54.9);

d1.Union(&d2);

So I want people can do something like this also.

DRect d1(2.3, 5.3, 98.2, 34.2);
IRect i(5, 4, 99, 54);

d1.Union(&i);

However, the compiler is only accept
'd.Union(&(static_cast<DRect>(i)));' form. My 'operator' functions are
wrong?

2. Where is the temporary object exist? stack?

operator DRect() const
{
return DRect(x0, y0, x1, y1);
}
operator DRect*() const
{
return &DRect(x0, y0, x1, y1);
}

If the temporary DRect object is exist on stack, it's still exist
when the 'DRect::Union' is executed?
Thanks.

May 18 '07 #1
4 2077
On May 17, 6:03 pm, zaemi...@gmail.com wrote:
I got a good answer here I have still confusing part.

I have two very simple classes

class DRect
{
private :
double x0, y0, x1, y1;
public :
DRect(double a, double b, double c, double d) : x0(a), y0(b),
x1(c), y1(d) {}
void Union(const DRect* p)
{
x0 = MIN(x0, p->x0);
y0 = MIN(y0, p->y0);
x1 = MAX(x1, p->x1);
y1 = MAX(y1, p->y1);
}

};

class IRect
{
private :
int x0, y0, x1, y1;
public :
IRect(int a, int b, int c, int d) : x0(a), y0(b), x1(c), y1(d)
{}
operator DRect() const
{
return DRect(x0, y0, x1, y1);
}
operator DRect*() const
{
return &DRect(x0, y0, x1, y1);
}

};

and the execution code here.

void main()
{
DRect d(5.3, 5.3, 15.6, 15.6);
IRect i(10, 10, 100, 100);

/* 1. No problem with compiling this code. */
d.Union(&(static_cast<DRect>(i)));

/* 2. It isn't compiled. */
d.Union(&i);

}

My question is

1. The second execution code 'd.Union(&i)' is quite resonable. People
usually do something like this.

DRect d1(2.3, 5.3, 98.2, 34.2);
DRect d2(5.2, 4.2, 99.1, 54.9);

d1.Union(&d2);

So I want people can do something like this also.

DRect d1(2.3, 5.3, 98.2, 34.2);
IRect i(5, 4, 99, 54);

d1.Union(&i);
The auto type conversion conforms to C++ standard. You can refer to
some materials. The conversion only happens in some special situation.
The compiler cannot find all the potential conversion for you.
>
However, the compiler is only accept
'd.Union(&(static_cast<DRect>(i)));' form. My 'operator' functions are
wrong?

2. Where is the temporary object exist? stack?

operator DRect() const
{
return DRect(x0, y0, x1, y1);
}
operator DRect*() const
{
return &DRect(x0, y0, x1, y1);
}

If the temporary DRect object is exist on stack, it's still exist
when the 'DRect::Union' is executed?
No! when the DRect function return, the temporary obj on stack will be
callbacked.
>
Thanks.

May 18 '07 #2
On 18 Maj, 03:03, zaemi...@gmail.com wrote:
I got a good answer here I have still confusing part.

I have two very simple classes

class DRect
{
private :
double x0, y0, x1, y1;
public :
DRect(double a, double b, double c, double d) : x0(a), y0(b),
x1(c), y1(d) {}
void Union(const DRect* p)
{
x0 = MIN(x0, p->x0);
y0 = MIN(y0, p->y0);
x1 = MAX(x1, p->x1);
y1 = MAX(y1, p->y1);
}

};

class IRect
{
private :
int x0, y0, x1, y1;
public :
IRect(int a, int b, int c, int d) : x0(a), y0(b), x1(c), y1(d)
{}
operator DRect() const
{
return DRect(x0, y0, x1, y1);
}
operator DRect*() const
{
return &DRect(x0, y0, x1, y1);
}

};

and the execution code here.

void main()
{
DRect d(5.3, 5.3, 15.6, 15.6);
IRect i(10, 10, 100, 100);

/* 1. No problem with compiling this code. */
d.Union(&(static_cast<DRect>(i)));

/* 2. It isn't compiled. */
d.Union(&i);

}
Use references instead, pointers should normally not be used unless
you have to.

#include <iostream>

class DRect {
private :
double x0, y0, x1, y1;
public :
DRect(double a, double b, double c, double d)
: x0(a), y0(b), x1(c), y1(d) {}

void Union(const DRect& p) {
std::cout << "Union";
}
};

class IRect {
private :
int x0, y0, x1, y1;
public :
IRect(int a, int b, int c, int d)
: x0(a), y0(b), x1(c), y1(d) {}

operator DRect() const {
return DRect(x0, y0, x1, y1);
}
};

int main() { // Notice int and not void as return-type
DRect d(5.3, 5.3, 15.6, 15.6);
IRect i(10, 10, 100, 100);
d.Union(i);
}

--
Erik Wikström

May 18 '07 #3
On May 18, 3:03 am, zaemi...@gmail.com wrote:
I got a good answer here I have still confusing part.

I have two very simple classes
class DRect
{
private :
double x0, y0, x1, y1;
public :
DRect(double a, double b, double c, double d) : x0(a), y0(b),
x1(c), y1(d) {}
void Union(const DRect* p)
{
x0 = MIN(x0, p->x0);
y0 = MIN(y0, p->y0);
x1 = MAX(x1, p->x1);
y1 = MAX(y1, p->y1);
}
};
class IRect
{
private :
int x0, y0, x1, y1;
public :
IRect(int a, int b, int c, int d) : x0(a), y0(b), x1(c), y1(d)
{}
operator DRect() const
{
return DRect(x0, y0, x1, y1);
}
operator DRect*() const
{
return &DRect(x0, y0, x1, y1);
}
};
and the execution code here.
void main()
Just a nit, but technically, this shouldn't compile. According
to the language specification, main() must return an int.
{
DRect d(5.3, 5.3, 15.6, 15.6);
IRect i(10, 10, 100, 100);
/* 1. No problem with compiling this code. */
d.Union(&(static_cast<DRect>(i)));
Really? It shouldn't compile---the result of the static cast
here is an rvalue, and you cannot take the address of an rvalue.
/* 2. It isn't compiled. */
d.Union(&i);
}
My question is
1. The second execution code 'd.Union(&i)' is quite resonable.
Not really. DRect and IRect are two classes unrelated by
inheritance. The fact that you can convert one of them to the
other doesn't mean that you can implicitly convert a pointer to
one to a pointer to the other. The relationship here is roughly
the same as that between int and double: an int converts
explicitly to a double, but an int* doesn't convert to a
double*.

The reason for this is, of course, obvious. If you have an int,
take it's address, and try to access it as a double, you're
going to get into deep trouble, very fast.
People usually do something like this.
DRect d1(2.3, 5.3, 98.2, 34.2);
DRect d2(5.2, 4.2, 99.1, 54.9);
d1.Union(&d2);
So I want people can do something like this also.
DRect d1(2.3, 5.3, 98.2, 34.2);
IRect i(5, 4, 99, 54);
d1.Union(&i);
Why the pointers? This looks like a case where references would
be more appropriate. The langage does allow using an rvalue (a
temporary) to initialize a reference to const.

This might even be a case where inheritance would be
appropriate. I don't know that actual application, but it seems
like you are saying that a user should be able to use an IRect
as a DRect; that is typically what inheritance is about. (On
the other hand, inheritance and assignment don't work very well
together, so if your class has value semantics, you might prefer
keeping the implicit conversions rather than using inheritance.)
However, the compiler is only accept
'd.Union(&(static_cast<DRect>(i)));' form. My 'operator' functions are
wrong?
Curiously enough, g++ only gives a warning here, even with
-std=c++98 -pedantic. Even more surprising, VC++ doesn't even
warn, unless you use /Za (in which case, it is an error). This,
despite the fact that it has never been legal, and that even the
earliest C compilers treated it as an error (so compatibility
with existing code cannot be the reason). It is, at any rate,
definitly illegal, and always has been. (Sun CC rejects it, and
as far as I know, doesn't have an option to allow it.)
2. Where is the temporary object exist? stack?
Where ever the compiler wants to put it. With a couple of
restrictions, however: the resulting code must be reentrant, and
(I think) the compiler may not generate a call to the global
operator new.

In practice, it will be in the same memory space where the
compiler puts local variables---on a machine with a stack,
almost certainly on the stack.
operator DRect() const
{
return DRect(x0, y0, x1, y1);
}
operator DRect*() const
{
return &DRect(x0, y0, x1, y1);
}
If the temporary DRect object is exist on stack, it's still exist
when the 'DRect::Union' is executed?
It exists until the end of the full expression in which it is
constructed. Since the full expression in your case includes
the call to DRect::Union, it will exist during this call. (You
would get into trouble, however, if DRect::Union saved the
pointer somewhere, and used it in a later function.)

Note that while there are different conventions with regards to
when to use references, and when to use pointers, every
convention I've ever heard of would use references in your case:
you don't accept null pointers, you don't modify the referenced
object, and you don't store the pointer for later use, after the
end of the function. And you want to be able to call the
function using temporaries (resulting from arbitrary
expressions or implicit type conversions).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 18 '07 #4
On May 18, 3:27 pm, xsws5...@gmail.com wrote:
On May 17, 6:03 pm, zaemi...@gmail.com wrote:
I got a good answer here I have still confusing part.
I have two very simple classes
class DRect
{
private :
double x0, y0, x1, y1;
public :
DRect(double a, double b, double c, double d) : x0(a), y0(b),
x1(c), y1(d) {}
void Union(const DRect* p)
{
x0 = MIN(x0, p->x0);
y0 = MIN(y0, p->y0);
x1 = MAX(x1, p->x1);
y1 = MAX(y1, p->y1);
}
};
class IRect
{
private :
int x0, y0, x1, y1;
public :
IRect(int a, int b, int c, int d) : x0(a), y0(b), x1(c), y1(d)
{}
operator DRect() const
{
return DRect(x0, y0, x1, y1);
}
operator DRect*() const
{
return &DRect(x0, y0, x1, y1);
}
};
and the execution code here.
void main()
{
DRect d(5.3, 5.3, 15.6, 15.6);
IRect i(10, 10, 100, 100);
/* 1. No problem with compiling this code. */
d.Union(&(static_cast<DRect>(i)));
/* 2. It isn't compiled. */
d.Union(&i);
}
My question is
1. The second execution code 'd.Union(&i)' is quite resonable. People
usually do something like this.
DRect d1(2.3, 5.3, 98.2, 34.2);
DRect d2(5.2, 4.2, 99.1, 54.9);
d1.Union(&d2);
So I want people can do something like this also.
DRect d1(2.3, 5.3, 98.2, 34.2);
IRect i(5, 4, 99, 54);
d1.Union(&i);

The auto type conversion conforms to C++ standard. You can refer to
some materials. The conversion only happens in some special situation.
The compiler cannot find all the potential conversion for you.
My opinion is different. Compiler knows "DRect::Union(const DRect*)"
function so when it meets 'd.Union(&i)', it knows that the type of 'i'
should be 'DRect' type. However it realizes 'i' is 'IRect' type and
tries to covert them into 'DRect' type.

There are some possible conversions.

1. Convert 'i'(DRect type) into 'const DRect' type and do address
operator(&). It makes 'i' to 'const DRect*' type.
=needs 'IRect::operator DRect()'

2. Convert '&i'(DRect* type) into 'const DRect*' type.
=needs 'IRect::operator DRect*()'

I still don't know why compiler doesn't do this.
>

However, the compiler is only accept
'd.Union(&(static_cast<DRect>(i)));' form. My 'operator' functions are
wrong?
2. Where is the temporary object exist? stack?
operator DRect() const
{
return DRect(x0, y0, x1, y1);
}
operator DRect*() const
{
return &DRect(x0, y0, x1, y1);
}
If the temporary DRect object is exist on stack, it's still exist
when the 'DRect::Union' is executed?

No! when the DRect function return, the temporary obj on stack will be
callbacked.
No, I don't think so. I do some more with compiler to understand this.

1. When the execution exists in 'main', the 'ESP' and call stack is
like this.

--------------------------------------------
ESP = 0012FEC4

main(int 1, char * * 0x003711c0) line 49
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c816fd7()
--------------------------------------------

2. When the execution exists in 'operator DRect', the 'ESP' and call
stack is like this.

--------------------------------------------
ESP = 0012FE68

IRect::operator DRect() line 36
main(int 1, char * * 0x003711c0) line 53 + 12 bytes
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c816fd7()
--------------------------------------------

3. Finally, when the execution exists in 'DRect::Union', the 'ESP' and
call stack is like this.

--------------------------------------------
ESP = 0012FE48

DRect::Union(const DRect * 0x0012ff30) line 17
main(int 1, char * * 0x003711c0) line 58
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c816fd7()
--------------------------------------------

As you can see, the address of the 'DRect::Union's argument('const
DRect*') is '0x0012ff30'.
It's below 'ESP = 0x0012FE48' which means the temporary DRect instance
is still safe in stack when the execution exists in
'DRect::Union'(Stack grows downward.).

Actually the memory for temporary DRect instance was allocated in
stack when the execution get into 'main' function

The above code, the local var's address is this.

d(local DRect instance) : 0x0012ff60
i(local IRect instance) : 0x0012ff50

*the temporary DRect instance from the type conversion : 0x0012ff30.

Am I right? That's what I understood from debugging.
>
Thanks.- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

May 18 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
by: frs | last post by:
See example below: Why does the output of 'a' work and the output of 'b' fails to compile? Is there a way to write class 'something' so that 'b' converts correctly by default? (include iostream,...
11
by: RWC | last post by:
Hello, I'm having trouble converting code in Access XP / 2002. I have some code that declares an variable "as database" in Access 97, which is not recognized in Access XP. I've tried to find a...
15
by: buda | last post by:
Let me see if I got this :) 1. I know the rules for type conversions in arithmetic expressions 2. I know that an implicit type conversion is done at assignment, so float x = 1.23; int t = (int)...
14
by: Just starting out | last post by:
I am very new to C code and I'm having a lot of trouble with a homework assignment. This program is supposed to take the amount of Euros that the user enters and convert it to US dollars. It...
12
by: Abhishek | last post by:
now suppose I have declared an integer value inside a function as int x; now if the return type of the function is of type (void *) then can I write return((void *)x) in side the function? I...
2
by: Martin v. Löwis | last post by:
I've been working on PEP 353 for some time now. Please comment, in particular if you are using 64-bit systems. Regards, Martin PEP: 353 Title: Using ssize_t as the index type Version:...
20
by: pinkfloydhomer | last post by:
Is it well-defined and portable to do something like: typedef struct { int type; char c; } S1; typedef struct {
1
by: zaeminkr | last post by:
I have a question about type conversion function for user defined type. I have two classes class DRect { private : double x0; double y0;
6
by: cppnow | last post by:
Hello. I have a strange conceptual problem I'm trying to think about. I would like to build a library that allows the user to do the following: 1) User defined types: The user defines their...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.