Thread: Casting issues...

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    14

    Question Casting issues...

    ok so I've come to the casting section of my book, and I've read and read, and this set of code seems to be right, all it says is that it can't convert down through the classes.

    Main.cpp
    Code:
    #include <iostream>
    #include <j:\Aaron's Documents\Visual Studio 2008\Projects\Trying the classes again\Trying the classes again\Animals.h>
    ;
    using namespace std;
    
    int main()
    {
    	Animal Fido;
    	Dog pFido = static_cast<Dog>(Fido); // casting, is it in the right format?
    	*pFido.play();
    	
    	system("PAUSE");
    	return 0;
    }
    and

    Classes.h
    Code:
    class Animal
    {
    	public:
    		Animal()  //Class to be cast from...
    		{ 
    			std::cout << "Creating Creature.\n";
    		};
    		~Animal()
    		{
    			std::cout << "Destroying Creature.\n";
    		};
    		int Age;
    		void
    			GetAge()
    		{
    			std::cout << "Creature is " << Age << " years old.\n";
    		};
    		void SetAge(int age)
    		{
    			Age = age;
    		};
    		void play()
    		{
    			std::cout << "Playing with Creature.\n";
    		};
    };
    
    class Fish : public Animal
    {
    public:
    	Fish()
    	{
    		std::cout << "Adding Fins, Gills, Scales.\n";
    	};
    	~Fish()
    	{
    		std::cout << "Removing Fins, Gills, Scales.\n";
    	};
    
    	void Swim(int sdist)
    	{
    		std::cout << "Fish swims " << sdist << " yards.\n";
    	};
    
    	void Float()
    	{
    		std::cout << "Fish remains floating.\n";
    	};
    };
    class Mammal : public Animal
    {
    public:
    	Mammal()
    	{
    		std::cout << "Adding Fur and Milk.\n";
    	};
    	~Mammal()
    	{
    		std::cout << "Removing Fur and Milk.\n";
    	};
    	
    	void rubfur()
    	{
    		std::cout << "Rubbing Fur.\n";
    	};
    };
    
    class Dog : public Mammal // class to be cast to...
    {
    public:
    	Dog()
    	{
    		std::cout << "Creating Dog.\n";
    	};
    	~Dog()
    	{
    		std::cout << "Destroying Dog.\n";
    	};
    	void run(int feet)
    	{
    		std::cout << "Dog runs " << feet << " feet.\n";
    	};
    
    	void play()
    	{
    		std::cout << "Playing with Dog.\n";
    	};
    }
    and errors:
    1.error C2440: 'static_cast' : cannot convert from 'Animal' to 'Dog'
    1>No constructor could take the source type, or constructor overload resolution was ambiguous
    2.main.cpp(Line 10) : error C2100: illegal indirection

    the first one seems pretty straightforward, but I don't know why it's saying it, what does it mean by "the constructor overload was ambiguous" , does it mean that it's trying to using two different constructors at once?

    Can someone tell me what it means?

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It says EITHER
    a) No constructor could do the conversion
    b) Constructor overload was ambiguous (two or more constructors was found that could do the conversion, but the compiler couldn't choose a best fit).
    In your case, it's a), because Dog has no constructor to take an Animal. The compiler simply doesn't know how to convert Animal to Dog.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    So how would I go about making a constructor that could take an Animal object?
    Could I make another? or would I have to change my current constructor to fit the Animal conversion?

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You can add as many constructors as you want.
    The form would be:
    Dog(const Animal& rhs)
    Dog is the constructor (naturally), which must take an Animal as argument (the object which it's going to copy). I use a reference to make it more efficient, and since a constructor should never modify the object it's copying, it takes it by const reference.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    thanks but that last problem is still there, I'm working in VC++ and it says it's an illegal indirection
    any reason why?

  6. #6
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    "Thanks Elysia. You're a programming master! How the hell do you know every thing?"

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Aaronugio View Post
    thanks but that last problem is still there, I'm working in VC++ and it says it's an illegal indirection
    any reason why?
    Because you try to dereference a non-pointer? o_O
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Change:
    Code:
    Dog pFido
    to:
    Code:
    Dog* pFido
    Although, you'll be lying to your compiler about what the real type is. It's not a Dog, it's just an Animal.
    You should be using dynamic_cast when doing upcasting/downcasting.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  9. #9
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    ah... thanks

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    This is polymorphism, btw, a separate topic.
    Since Dog inherits from Animal, it is also an Animal, thus you can convert a Dog into an Animal without problems, no casting required. That's not always the case the other way around, however.
    Polymorphism only works with pointers and references. Beware.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    I know that I'm just trying to get a grasp of casting, for possible future purposes, none in mind yet...

    ok, I changed my animal to a pointer, and the situation is pretty much back at the start
    I'm confused now entirely

    Code:
    #include <iostream>
    #include <j:\Aaron's Documents\Visual Studio 2008\Projects\Trying the classes again\Trying the classes again\Animals.h>
    ;
    using namespace std;
    
    int main()
    {
    	
    	Animal *pAnimal;
    	Dog* pFido = static_cast<Dog>(pAnimal);
    	*pFido.play();
    	
    	system("PAUSE");
    	return 0;
    }
    and

    Code:
    class Dog : public Mammal
    {
    public:
    	Dog()
    	{
    		std::cout << "Creating Dog.\n";
    	};
    	~Dog()
    	{
    		std::cout << "Destroying Dog.\n";
    	};
    	Dog(const Animal &rhs)
    	{
    		std::cout << "Converting Animal to Dog.\n";
    	};
    
    	void run(int feet)
    	{
    		std::cout << "Dog runs " << feet << " feet.\n";
    	};
    
    	void play()
    	{
    		std::cout << "Playing with Dog.\n";
    	};
    }
    and if I've made any ridiculously obvious mistakes, please forgive me, I'm still trying to learn it...

    and it tells me:
    (1)main.cpp(10)error C2440: 'static_cast' : cannot convert from 'Animal *' to 'Dog'
    1> No constructor could take the source type, or constructor overload resolution was ambiguous
    (2) main.cpp(11) : error C2100: illegal indirection

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Several issues...
    You are trying to convert a pointer to a non-pointer. You want to change the type of your Animal* to Dog* (both pointers). Use dynamic_cast for this, because we're working with polymorphism.
    Second problem is due to operator precedence.
    *pFido.play();
    Is the same as
    (*pFido.play());
    Meaning it will dereference whatever the member function play() returns. However, pFido is a pointer, and pointers do no have members. Furthermore, play doesn't return a pointer that can be dereferenced!
    What you want to do is dereference the pointer first and call a member function. We tell the compiler to evaluate that first:
    (*pFido).play();
    That will work, but is rather vulgar, and it turns out there's an easier way to do it:
    pFido->play();

    That leads to the 3rd issue.
    pFido points to nowhere. It has no allocated memory and thus you cannot call any member functions in it. You must properly learn pointers. Either point them to an object or dynamically allocate (and later free) an object.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Registered User
    Join Date
    Jul 2009
    Posts
    14
    ok, so I've edited it, and yet again, it compiles, but gives me the same message:

    "First-chance exception at 0x004115e6 in Casting Test.exe: 0xC0000005: Access violation reading location 0x00000000.
    Unhandled exception at 0x004115e6 in Casting Test.exe: 0xC0000005: Access violation reading location 0x00000000."


    Code:
    #include <iostream>
    #include <j:\Aaron's Documents\Visual Studio 2008\Projects\Trying the classes again\Trying the classes again\Animals.h>
    ;
    using namespace std;
    
    int main()
    {
    	Animal *pAnimal = new Animal;
    	Dog* pDog = dynamic_cast<Dog*>(pAnimal);
    
    	pDog->play();
    	
    	system("PAUSE");
    	return 0;
    }
    Where have I messed up?

    Thank you for all you've done to help me

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    If dynamic_cast fails, you will get a NULL pointer back (see all those zeroes?) -- and your dynamic_cast will fail, because an Animal cannot become a Dog. (A Dog can be considered an Animal, but not vice versa.)

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    There's also still two problems in the code:
    1) You are creating an Animal. Animal != Dog. So you are treading a very fine line when you're casting the Animal into a Dog. It's would be another thing if you actually created a Dog instead of an Animal.
    2) You MUST delete everything that you new. Better yet is some smart pointer, such as std::auto_ptr which works well in this case.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Advantages of c++ type casting over c type casting
    By kaibalya2008 in forum C++ Programming
    Replies: 10
    Last Post: 05-05-2009, 11:09 AM
  2. Casting Question (I think)
    By fayte in forum C Programming
    Replies: 6
    Last Post: 03-08-2006, 05:31 PM
  3. casting the system exstracted date into seperate ints
    By bazzano in forum C Programming
    Replies: 1
    Last Post: 08-30-2005, 12:17 AM
  4. Type casting
    By Lionmane in forum C Programming
    Replies: 28
    Last Post: 08-20-2005, 02:16 PM
  5. question about casting pointers/other types also??
    By newbie02 in forum C++ Programming
    Replies: 3
    Last Post: 08-07-2003, 05:01 AM

Tags for this Thread