Re: CPtrList - Please Help me understand
From: Joseph M. Newcomer (newcomer_at_flounder.com)
Date: 09/01/04
- Next message: Joseph M. Newcomer: "Re: Custom Resources"
- Previous message: Peter: "Re: CScrollView constructor"
- In reply to: Joseph M. Newcomer: "Re: CPtrList - Please Help me understand"
- Messages sorted by: [ date ] [ thread ]
Date: Wed, 01 Sep 2004 04:37:17 -0400
I meant to add, you would have been better off declaring your own CList, e.g.,
CList<notice *, notice *>notices;
instead of
CPtrList notices;
then all of this disappears, and you can ignore it, because the GetAt() will return an
object of type notice*, and you won't need to do casts at all.
joe
On Tue, 31 Aug 2004 17:54:26 -0400, Joseph M. Newcomer <newcomer@flounder.com> wrote:
>Depends on what sort of object you are storing things in. Since you have a CPtrList, it
>holds generic pointers, of type void *. This means that GetAt() returns only a void *,
>which cannot be stored into a variable of any other type. Thus you could write
>
>void * temp = m_list.GetAt(pos);
>
>and the compiler would be happy. But the rules of C++ do not permit taking a pointer of a
>higher class (void * is the "root class" of all other classes) and assigning it to a
>specialized subclass. This is just a special case of
>
>class A { ... };
>class B : public A { ... }
>
>B * bp = new B;
>A * ap = bp; // valid
>B * bp2 = ap;
>
>Now although bp has a pointer to an object of type B (which we know because we created
>one), and it is valid to assign it to an A* (because all Bs are As), the third assignment
>is invalid by the rules of C++ because it doesn't know if the thing in ap is a B or an A.
>Note that if we did
>
>class C : public A { ... }
>
>it would be valid to do
>A * ap = new C;
>but then it would be nonsensical to do
>B * bp2 = ap;
>because the thing in A, although it is an A, and a C, is not a B.
>
>There are several ways to handle this. The simplest method is to do
>
>B * bp2 = (B *)ap;
>
>the construct (type)expression tells the compiler to treat expression as if it were
>(type), and not whatever it turns out to be.
>
>So although ap is an A*, you insist to the compiler that it is really a B*, so the
>compiler now happily does the assignment.
>
>The only problem with this is with the class C. Suppose I did
>
>A * ap = new C;
>B * bp2 = (B*)ap;
>
>the compiler is happy, it does what it is supposed to, and does essentially an illegal
>assignment, because the thing in ap is in fact NOT a B*, but a C*!
>
>Many people are offended by this. Unforutnately, the solution is somewhat clumsy, but is a
>better solution. You would write
>
>B * bp2 = dynamic_cast<B *>ap;
>
>which forces a runtime check of the object referenced by ap. If it is of type B*, the
>assignment takes place; if it is not of type B* (such as being a C*) then the NULL pointer
>value is assigned to bp2, which you can then check. This is known as a "safe cast-down",
>since it casts the type to a type which is lower in the type hierarchy, and does so
>safely.
>
>The shorter form is more convenient to use, and does not require run-time-type-information
>(RTTI) to be enabled, but is, in fact, potentially unsafe. The form
> (B*)ap
>is the same as
> static_cast<B*>ap
>
>Generally, casting has no effect on the representation of a value, other than instructing
>the compiler to trust you. So in 32-bit windows (and this is poor practice but it
>illustrates a point)
> DWORD w = (DWORD)ap;
>takes the pointer ap which is a 32-bit value, and tells the compiler to treat it as a
>DWORD (integer value) in terms of type checking (the reason this is poor practice is that
>with the introduction of 64-bit machines, a pointer is now 64 bits and a DWORD is 32 bits)
>so the correct representation would be
> DWORD_PTR w = (DWORD_PTR)ap;
>because a DWORD_PTR is an integer type big enough to hold a pointer, but otherwise behaves
>as an integer, but you don't need to worry about this until you get more advanced.
>
>But this rule falls apart with the casts between integer values and floating-point values.
>So
>
>double d = 2.95;
>int n = (int)d;
>double p = (double)n;
>
>actually DOES change the representation. In the first case, where d is being assigned to
>n, the floating-point representation 2.1, which is 64 bits with a mantissa and exponent
>component, is converted to an integer (discarding the .95! It doesn't round!) is converted
>to the integer 2. In the second case, where n is being assigned to p, the 32-bit integer
>value is converted to a 64-bit floating-point value with a mantissa and exponent
>representation, which is quite different.
>
>Note that if you saw the value 3, it might have been 2.99999999999999 internally, but
>printed as 3, so where you do
> int n = (int)d;
>you will actually get the number 2, not 3. The solution to this is to write, if you want
>to be reasonably accurate and have rounding handled properly,
> int n = (int) (d < 0 ? d - 0.5 : d + 0.5)
>which does the correct rounding to the expected integer value.
> joe
>
>On 31 Aug 2004 12:28:56 -0700, victor75040@yahoo.com (victor) wrote:
>
>>Hi All,
>>
>>I have a tutorial where I am trying to understand something, I have a
>>fairly good grip as to how pointers work. Here is what I have.
>>
>>Struct notice
>>{
>> CString notedata;
>> int numberofdata;
>>}
>>
>>I also have a CPtrList object m_list, to wich I have added several
>>nodes of the
>>type Struct notice.
>>
>>Now the tutorial shows the line below:
>>
>>notice *temp = (notice *) m_list.GetAt(pos);
>>
>>I understand the part left of the = sign means create a pointer var
>>temp of the type notice, but I am having a diffcult time understanding
>>the part (notice *) to the right of the = sign. Can someone please
>>break this down and explain is simple term. I understand the
>>m_list.GetAt(pos) part, just the (notice*) is confusing the heck out
>>of me.
>>
>>Thanks
>>
>>Victor
>>victor75040@yahoo.com
>
>Joseph M. Newcomer [MVP]
>email: newcomer@flounder.com
>Web: http://www.flounder.com
>MVP Tips: http://www.flounder.com/mvp_tips.htm
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
- Next message: Joseph M. Newcomer: "Re: Custom Resources"
- Previous message: Peter: "Re: CScrollView constructor"
- In reply to: Joseph M. Newcomer: "Re: CPtrList - Please Help me understand"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|