1

Why can you do this:

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;
}

Why is padd = (Addition*) &d; valid when it will generate a run-time error whenever it gets used afterwards? A quote from cplusplus.com:

Unrestricted explicit type-casting allows to convert any pointer into any other pointer type, independently of the types they point to.

But why can you convert any pointer into any other pointer type just if you precede the reference with a casting operator?

Talking about that casting operator, how can it convert all types to another type? Does it call a conversion constructor because if so, I do not get it, because both Dummy nor Addition do not have a conversion constructor so how does this operation work then? How many operators does it have and is it the parentheses that are the operator itself, like = is an operator.

  • It just casts the pointer, no constructors are called. The runtime error will occur likely when you try to access any field of `Addition` for this pointer. – gmoshkin Jun 08 '17 at 15:52
  • Don't use cplusplus.com as a textbook, choose one from [here](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) instead – Passer By Jun 08 '17 at 15:52
  • You can do it because C allows you to. –  Jun 08 '17 at 15:53
  • C++ allows you to do a lot of things, but it doesn't mean you should be using them. – gmoshkin Jun 08 '17 at 15:54

3 Answers3

2

These kinds of casts are C style casts, and will let you cast just about anything to anything else. A cast is a statement to the compiler to disregard it's type safety rules and trust that you know best. This is sometimes necessary when the type system can't have all the information it needs to reach the right conclusions. However, if you are lying to the compiler about something's type, then you are producing undefined behavior.

In c++, you should avoid preforming C style casts and prefer the safer c++ alternatives (listed here. Theses casts can't completely protect you from yourself, but they do allow you to communicate the kind of cast you want to preform. Using this extra information, the compiler can warn you if your casts would do something other than what you expect them to do.

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
  • Well thanks. I read that link and cppreference said "When the C-style cast expression is encountered, the compiler attempts to interpret it as the following cast expressions, in this order:...". So does this mean that the compiler spends time trying all the different cast expressions when using the c-style cast? Why is that? :/ –  Jun 08 '17 at 16:37
  • @OfT When you use a C++ cast, you tell the compiler why you want to do casting. This lets the compiler catch additional mistakes. When you use a C cast, the compiler must make a guess, so it tries all different reasons starting with the least "intrusive", and stops when it finds a corresponding C++ cast that would not result in an error. – Sergey Kalinichenko Jun 08 '17 at 17:07
  • @OfT Yes. The compiler has to figure out which cast to preform because they don't all do the same thing. For example `static_cast` often compiles to a CPU instruction while `reinterpret_cast` never does. – François Andrieux Jun 08 '17 at 17:23
  • Ahh okay great. But doesn't that make the compile time slower since it has to go through them all? I mean vs a specific cast, such as static_cast? @dasblinkenlight and/or Francois? –  Jun 08 '17 at 17:57
  • @OfT C++ compiler can go through these possibilities in a matter of microseconds, so increased compile time is definitely not a concern here. – Sergey Kalinichenko Jun 08 '17 at 18:00
  • @dasblinkenlight, thanks again. But how come that you can use the C-style cast with any pointer type as the destination type, like (classX*)aVariable, on all variables but you cannot use non-pointer type like (classX)aVariable, on all types and it requires a conversion constructor/assigment? –  Jun 08 '17 at 18:28
  • That is the final thing that I do not really get about this :)) @dasblinkenlight –  Jun 08 '17 at 19:07
  • Of course Francois you are also more than welcome to answer :))))))))))) –  Jun 08 '17 at 19:22
  • @OfT The standard covers how casts should behave for all types of pointer conversions. Generally it simply returns a pointer of the new type with the same address. It does not cover how to convert between unrelated class types, it's impossible to know what the right thing to do is. That's why the compiler needs to rely on user provided conversion operators and constructors. What should `x` be in `x = static_cast(y);` where `y` is of unrelated type `bar`? You have to tell the compiler how to preform that operation. – François Andrieux Jun 08 '17 at 20:14
  • Thank you Francois! –  Jun 08 '17 at 21:46
1

When you use:

padd = (Addition*) &d;

the compiler assumes that you, the person in charge, know what you are doing. If you shoot yourself in the foot, that's of your own choosing. The compiler is happy to let you do that.

If you would like the compiler to prevent you from such accidental, shoot-yourself-in-the-foot, situations, use static_cast.

padd = static_cast<Addition*>(&d);

The compiler will let you know that that is not OK.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

If you use a C style cast, there is no check for errors or compatibility between the pointers. Also, I think you misunderstand the purpose of the unary operator &, in this case it gives the address of d and is not related to references.

Objects in memory are just bits that the program knows to be some type, if you tell it that it is another type it will not affect anything in the variable.

MrPromethee
  • 721
  • 9
  • 18