[Newbie]How to implement type inheritance?

This is a discussion on [Newbie]How to implement type inheritance? within the C++ Programming forums, part of the General Programming Boards category; An Animal can be a Dog, Fish, Bird, etc A Dog can be a Shepherd, Terrier, etc A Fish can ...

  1. #1
    vyn
    vyn is offline
    Registered User
    Join Date
    Nov 2008
    Posts
    7

    [Newbie]How to implement type inheritance?

    An Animal can be a Dog, Fish, Bird, etc

    A Dog can be a Shepherd, Terrier, etc
    A Fish can be a Guppy, Salmon, etc


    getAnimal(InputStream) reads some input from the input stream and returns an object of type Animal.
    A checking function repeatedly calls getAnimal and checks what kind of Animal is returned(Dog, Fish, etc), then checks the specific type of animal(Guppy, Salmon, etc), and does some computation.

    How should the datatype Animal be implemented? An enum/struct/typedef/class? How then would I go about implementing the checking function? I was thinking of something like the following:

    Code:
    Animal a = getAnimal(inputStream);
    switch (a) {
    	case DOG:
    		do something
    		case SHEPERD:
    			do something:
    		case TERRIER:
    			do something:
    	case FISH:
    		do something
    		case GUPPY:
    			do something:
    		case SALMON:
    			do something:
    	....
    }
    The syntax and case construct is slightly broken but I hope you get the idea.

  2. #2
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,762
    You're doing this completely wrong.

    If you don't have enough input to construct an animal (or Dog or whatever), then don't construct one. Constructors aren't supposed to fail.

    So either:
    1. Write constructors that never fail.
    2. Or throw an exception when they do fail.

    For the other part of this question, dynamic binding can remove the problem of run time type identification in a number of cases. This is when you take a pointer of the parent type and cast it to the type you're working with.

    Animal *pet = getAnimal(cin);
    Dog *myDog = dynamic_cast<Dog *>(pet);

    or

    Fish *myFish = dynamic_cast<Fish *>(pet);

    Naturally, dynamic_cast can fail and will fail if A* is not controvertible to B*, so you still need to make sure it works.

  3. #3
    Registered User
    Join Date
    Apr 2006
    Posts
    2,053
    If you want to use polymorphism then you're doing it wrong. I should look something like this:
    Code:
    class Animal{
      virtural void do_something() = 0;
      virtual ~Animal();
    }
    
    class Dog: public Animal{
      void do_something(){
        //stuff...
        do_something_else();
      }
      virtual void do_something_else() = 0;
      virtual ~Dog();
    }
    
    class Shepard: public Dog{
      void do_something_else();
    }
    
    //then you use it like
    Animal *animal = getAnimal(inputStream);
    animal->do_something();
    On a different note, don't call the function getAnimal(). Functions beginning with get are generally used as accessors to get a class's data, and that's not what you are doing here.
    Last edited by King Mir; 08-26-2009 at 05:57 AM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  4. #4
    Registered User
    Join Date
    Apr 2006
    Posts
    2,053
    Quote Originally Posted by whiteflags View Post
    You're doing this completely wrong.

    If you don't have enough input to construct an animal (or Dog or whatever), then don't construct one. Constructors aren't supposed to fail.

    So either:
    1. Write constructors that never fail.
    2. Or throw an exception when they do fail.
    getAnimal is not a constructor. That not a problem here.

    For the other part of this question, dynamic binding can remove the problem of run time type identification in a number of cases. This is when you take a pointer of the parent type and cast it to the type you're working with.

    Animal *pet = getAnimal(cin);
    Dog *myDog = dynamic_cast<Dog *>(pet);

    or

    Fish *myFish = dynamic_cast<Fish *>(pet);

    Naturally, dynamic_cast can fail and will fail if A* is not controvertible to B*, so you still need to make sure it works.
    This undermines the entire purpose of making Dog and fish a subclass of animal. Don't use dynamic cast for something like this. If you think you need dynamic cast, think again, cause your probably wrong.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  5. #5
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,762
    Quote Originally Posted by King Mir View Post
    getAnimal is not a constructor. That not a problem here.

    This undermines the entire purpose of making Dog and fish a subclass of animal. Don't use dynamic cast for something like this. If you think you need dynamic cast, think again, cause your probably wrong.
    Uh huh but I think you are wrong, too. If animal is an abstract base class, then stack objects of it should not compile (because they're abstract). So your code doesn't work either. OTOH pointers to animal, being a different type than animal, are OK. But some type of cast is necessary between animal* and any of its' children, perhaps I picked the wrong one.

    If dynamic_cast is really wrong here, please explain why. Anyone.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by whiteflags View Post
    But some type of cast is necessary between animal* and any of its' children, perhaps I picked the wrong one.
    Why would a cast be necessary? The king at 12:28 gave a perfectly good example with no casting whatsoever. That's the point of virtual, after all, is to pick the right function based on type....

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,304
    Quote Originally Posted by tabstop
    The king at 12:28 gave a perfectly good example with no casting whatsoever. That's the point of virtual, after all, is to pick the right function based on type....
    The problem is that King Mir's example is wrong, precisely because of the point that whiteflags raised: animal is of type Animal, which is an abstract base class, instead of type Animal& or (smart) pointer to Animal. Consequently, there will be a compile error, and if we change the type to a concrete base class, there would be no polymorphism.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by laserlight View Post
    The problem is that King Mir's example is wrong, precisely because of the point that whiteflags raised: animal is of type Animal, which is an abstract base class, instead of type Animal& or (smart) pointer to Animal. Consequently, there will be a compile error, and if we change the type to a concrete base class, there would be no polymorphism.
    Man man man. Of course that's what I wanted to see, so that's what I saw.

    All right, try again. The OP says "getAnimal(InputStream) reads some input from the input stream and returns an object of type Animal." If that function returns an echte Animal object, then I think we're sunk no matter what if we try to be polymorphic, so we would have to store the type and have some unnecessary class variables (or, if we're feeling rambunctious, maybe a union). If that function returns by reference, then we can assign to a reference and everybody's happy (I think).

  9. #9
    Registered User
    Join Date
    Apr 2006
    Posts
    2,053
    Well change it to return a pointer then. I did not compile or extensively check the example I wrote. But yeah, getAnimal() needs to return a pointer or reference for it to work. I fixed it above.

    If getAnimal() must return an Animal by value, then there is no point in making subclasses of it. Instead you would have to use a member enum to determine what type of animal you are dealing with.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,027
    If the function returns by value, you are screwed because the objected will be sliced.
    Then you'd have to make a big monolithic class of all the different types of animals and some sort of identifier to know which type it is. Tedious and just ... wrong.
    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. Quantum Random Bit Generator
    By shawnt in forum C++ Programming
    Replies: 62
    Last Post: 06-18-2008, 11:17 AM
  2. Cant find the error
    By Coder87C in forum C Programming
    Replies: 8
    Last Post: 06-19-2005, 02:57 AM
  3. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 07:49 PM
  4. odd errors from msvc std library files
    By blight2c in forum C++ Programming
    Replies: 6
    Last Post: 04-30-2002, 01:06 AM
  5. gcc problem
    By bjdea1 in forum Linux Programming
    Replies: 13
    Last Post: 04-29-2002, 07:51 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21