0

Code:

class Dummy {
    double i,j;
};

class Addition {
    int x,y;
  public:
    Addition (int a, int b) { x=a; y=b; }
    int result() { return x+y;}
};

int main () {
  Dummy d;
  Addition * padd;
  padd = (Addition*) &d;
  //cout << padd->result();
  return 0;
}

Questions:

  • Why can you do this padd = (Addition*) &d; but not this padd = (Addition) &d;?
  • When declaring an object of Addition like Addition padd instead of Addition* padd, why does it ask for a constructor, which it doesn't when declaring a pointer?
  • you didn't initialize any fields – phuclv Jun 09 '17 at 10:46
  • A pointer is just a number telling you where in memory an object is supposed to be. You can cast a pointer to any other pointer because every pointer is the exact same thing: a number (that can be used to point to memory). Objects and other datatypes are more complex and not necessarily compatible with each other. Also keep in mind that just because you can cast a pointer, doesn't mean dereferencing it won't crash your program or otherwise invoke undefined behavior, because at that point you will attempt to access an actual object. – Zinki Jun 09 '17 at 10:49
  • 3
    Avoid C-style casts and use C++ casts like `static_cast` or `dynamic_cast` instead and then you will find that this code doesn't compile. – Chris Drew Jun 09 '17 at 10:51
  • 1
    One question per question please – Lightness Races in Orbit Jun 09 '17 at 10:58

3 Answers3

0

Taking the address of a variable returns a pointer, which is a very different thing than the original variable. A pointer is just a memory address (usually the size of an int), while the object pointed can be anything from char to a huge table or a stream. So you can definitively not cast a pointer in non-pointer type (and vice-versa), and (Addition) &d can not work.

When you type Addition padd;, you build an object of type Addition which the default constructor. When you type Addition* padd;, you just declare a pointer, so a memory address, and no object is created.

Finally, be careful with the C cast (the type in parenthesis in front of the variable). This cast will try several C++ cast until it succeeds (from static_cast to reinterpret_cast), and you can easily find yourself on an undefined behavior. See this for instance.

gaFF
  • 747
  • 3
  • 11
  • I think today it's no really appropriate anymore to assume pointer size as *usually the size of an `int`*. 64 bit is out for a long time by now. – grek40 Jun 09 '17 at 11:03
0

Basically you asking what is the difference between an object and a pointer to an object?

Object is a region of storage. A pointer is just a an integer pointing an offset in this storage. A pointer physically (after making a binary out of code) does not differ from an object of one type to an object of another type - always an integer. On the other hand, object is a region that has an offset and a size. That two basic matters that C++ distinguishes.

Why can you do this padd = (Addition*) &d; but not this padd = (Addition) &d;?

Like it is said above all pointers are physically the same (i.e. integers). That is why it is always possible to do the former. Mind that at the end dereferencing this pointer is undefined behavior. However it does not seem feasible for the compiler to convert to different matters (pointer to storage).

When declaring an object of Addition like Addition padd instead of Addition* padd, why does it ask for a constructor, which it doesn't when declaring a pointer?

Again pointer is just an integer, you do not need anything else to create it. However, Addition is a storage shat is type that has no default constructor that is why you have to provide other objects to initialize it.

By the way, pointers are also object, that is why you can have a pointer to a pointer and etc.

In addition:

  • Pointers to void, objects, functions are very different from pointers to members;

  • Pointers to void, objects, functions must not be assumed to have a fixed size, size might be varying on some platforms, compilers, but not larger than void*.

Yuki
  • 3,857
  • 5
  • 25
  • 43
  • Yes, I did not mean pointers to members, if you are about that, otherwise could you give a hint what you mean? – Yuki Jun 09 '17 at 13:05
  • 1
    The C++ standard gives a lot of latitude about what happens when you try to use a pointer of the wrong kind. While all pointers must be storable in a `void*`, it permits a `char*` to be *larger* than a `int*` last I checked (which is useful if your system has dword-addressing, yet you still want 8 bit char, and you don't want to waste space on `int*`s). In short, what works on most desktop machines is not what the C++ standard requires to work. Throw in "in most implementations of C++ you will ever work with" and your claim is true (outside of pmf and pmd). – Yakk - Adam Nevraumont Jun 09 '17 at 13:35
0

A simple simile that indirectly answers your questions:

  • Pointers are like real-life signs.

  • A sign pointing to a lake is similar to a sign pointing to a building (but you can also use a different definition of "similar" which will say these things aren't similar).
    A sign pointing to a lake is not similar to an actual lake or building.

    Now when you assume a sign is pointing to a lake when it's in fact pointing to a building, and you try to treat that building like a lake (by e.g. swimming in it), you're going to have problems.

    That is to say: C++ would run code that casts between incompatible pointers, but trying to access the object the pointer you incorrectly cast is pointing to probably won't work so well for you.

  • Making a new sign doesn't require that you also make the thing you want it to point to.
    You can have a sign to a lake that doesn't actually point to a lake (yet?), or you can point it to an existing lake.

&lake gives you a sign to lake.

Disclaimer: I might've borrowed the core idea from someone else.

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138