0

This example is from C++ in easy steps 5th ed (Mike McGrath) - Ch 8 Polymorphism, "Pointing to Classes".

I was wondering if anyone ran into this before or know why this fails to compile. I followed the example from the book and for some reason my program fails to compile and throws an exception related to casting. I even tried this on an online cpp compiler and got the same compiler exception so this rules out my compiler. I'm using the g++ compiler on Ubuntu. Please see attached screenshot. If anyone can assist that would be greatly appreciated! [Pointing to classes screenshot]

#include <iostream>
using namespace std;

class Base
{
    public:
     void Identify(int adr) const   
     {
         cout << "Base class called by 0x" << hex << adr << endl;
     }
};

class SubA : public Base {  };
class SubB : public Base {  };

int main()
{
    // create 2 base class pointers each binding to a specific derived class
    Base* ptrA = new SubA;      //or ... SubA a; Base* ptrA = &a;
    Base* ptrB = new SubB;      //or ... SubB b; Base* ptrB = &b;

    // use the pointers to call the base class method, passing the memory address of each for output
    ptrA -> Identify((int) &ptrA); 
    ptrB -> Identify((int) &ptrB);

    return 0;
}

Here's the compiler exception being thrown:

g++ classptr.cpp -o classptr classptr.cpp: In function ‘int main()’: classptr.cpp:29:26: error: cast from ‘Base**’ to ‘int’ loses precision [-fpermissive] ptrA -> Identify((int) &ptrA);

classptr.cpp:30:26: error: cast from ‘Base**’ to ‘int’ loses precision [-fpermissive] ptrB -> Identify((int) &ptrB);

L393nd
  • 25
  • 5
  • 1
    Please add the program as text, not as a link, or an image. – cigien May 11 '20 at 01:02
  • Just change int to void* for the adr param to Identify. – manuell May 12 '20 at 06:55
  • @manuell thanks, but isn't using (void*) generally considered bad practice? I always like to specify my types to avoid potential bugs that can arise – L393nd May 14 '20 at 01:12
  • @L393nd But your `Identify` method wants an address, not an integer! And you want it to be callable with address of different type! `void*` is the correct type, here. If you "specify" your type but then have to use casting, that's a problem, no? (hence your question...) – manuell May 14 '20 at 08:40

1 Answers1

0

Try changing this line ptrA -> Identify((int) &ptrA); to this ptrA -> Identify((long) &ptrA);

On most platforms pointers and longs are the same size, but ints and pointers often are not the same size on 64bit platforms. If you convert (Base*) to (long) no precision is lost, then by assigning the (long) to an (int), it properly truncates the number to fit.

Nick Juelich
  • 428
  • 2
  • 13
  • Thanks a ton! (long) was the magic answer. I can't believe it slipped me. It all makes sense now since I am using a 64-bit platform with a greater memory pool. This was keeping me up all night, now I can finally get some rest :) – L393nd May 12 '20 at 02:16
  • On 64 bits Windows, long are 32 bits. – manuell May 12 '20 at 06:52
  • @manuell I thought int is 4 bytes (32 bits) and long is 8 bytes (64 bits). Maybe I'm missing something? – L393nd May 14 '20 at 01:03
  • Yes, you are missing something :-) Read the answers here: https://stackoverflow.com/questions/11438794/is-the-size-of-c-int-2-bytes-or-4-bytes – manuell May 14 '20 at 08:43
  • I was referring to cpp not C, thanks for the link. And there is never a concrete answer to this as it also dpends on the compiler too. For 32 bit systems, a long is the same as an int in terms of size which many sources claim 2-4 bytes. For 64-bit platforms longs use up more than 4 bytes up to 8 bytes so I think you meant to say 32-bit where a long is 4 bytes which would be correct. The only way to know for certain is do sizeof(int) and sizeof(long) and run it and it should give the right answer for your specific hardware – L393nd May 16 '20 at 00:15
  • For example on my 64-bit system, my sizeof(int) is 4 bytes and sizeof(long) is 8 bytes which is in line with what sources are saying and i'm using a g++ compiler on linux. Maybe on Mac or Windows its different, I am just showing what linux is revealing the size to be because its much closer to the metal than windows is, there is less abstraction, thus less variables at play here, so the #s are much more accurate – L393nd May 16 '20 at 02:59