Thread: How do make a difference between inherited classes for functions?

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

    How do make a difference between inherited classes for functions?

    Hi.
    I want to create an abstract class C and subclasses A and B (they both inherit from C) and then I want to have a function called "foo" with the following definitions
    Code:
    C* foo(A* x, A* y);
    C* foo(B* x,B* y);
    C* foo(A* x,B* y);
    C* foo(B* x,A* x);
    where the object that is returned(pointed to) is of class A only if foo is called with A*, A* arguments and otherwise it's a B object.
    So foo must be overloaded, but how can the different objects be identified at runtime?

    How can I make this work? How do I write foo?

  2. #2
    Banned
    Join Date
    Jun 2005
    Posts
    594
    either of these two may give
    you some insight on hwo to accomplish
    what you want.

    http://www.cplusplus.com/doc/tutorial/tut4-4.html

    or

    http://cplus.about.com/od/beginnerct.../aa121702b.htm

  3. #3
    Registered User
    Join Date
    Jul 2005
    Posts
    14
    The problem is: how can the program know if I a C pointer points to a dynamicaly created A or B object?

  4. #4
    Banned
    Join Date
    Jun 2005
    Posts
    594
    http://cboard.cprogramming.com/showthread.php?t=68062

    maybe this, and i dont have much experience in what your trying
    to do. maybe a littel more detail and ill figure it out,
    possibly the all the code you have now or so.

  5. #5
    Registered User
    Join Date
    Jul 2005
    Posts
    14
    Thanks, I look more into those examples.
    I have no code, I want to know how to write the code before starting :-)

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    In general, you shouldn't have to know what type a C* points to, you just use it and it works. One instance where you might want to know the type is if you are creating a new object. One way to do this would be to create a Factory method. Create the factory method separate from the base class. Create an enum of identifiers, one for each derived class type. Then create a virtual function in the base class that returns a member of the enum (or just an int). The derived classes will override this virtual function to return the enum that corresponds to them. This requires no extra space in the class instances, but safely distinguishes each derived class. You would pass the result of caling this function to your Factory method that would then create the appropriate type of object.

  7. #7
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    I'm not sure if I understood correctly, but it seems simple enough. Look at this code:
    Code:
    #include <iostream>
    
    class Base
    {
    public:
    	virtual void Print() = 0;
    };
    
    class A : public Base
    {
    public:
    	virtual void Print()
    	{
    		std::cout << "I am a class A" << std::endl;
    	}
    };
    
    class B : public Base
    {
    public:
    	virtual void Print()
    	{
    		std::cout << "I am a class B" << std::endl;
    	}
    };
    
    Base* foo(A* obj1, A* obj2)
    {
    	return obj1; //return an A*
    }
    Base* foo(A* obj1, B* obj2)
    {
    	return obj1; //return an A*
    }
    Base* foo(B* obj1, A* obj2)
    {
    	return obj2; //return an A*
    }
    Base* foo(B* obj1, Base* obj2)
    {
    	return obj1; //no A*, return a Base*
    }
    
    int main()
    {
    	A a;
    	B b;
    	foo(&a,&a)->Print();
    	foo(&a,&b)->Print();
    	foo(&b,&a)->Print();
    	foo(&b,&b)->Print();
    	return 0;
    }
    However, it's much simpler to use a dynamic_cast; instead of 4 functions, you only need one function. Consider this:
    Code:
    #include <iostream>
    
    class Base
    {
    public:
    	virtual void Print() = 0;
    };
    
    class A : public Base
    {
    public:
    	virtual void Print()
    	{
    		std::cout << "I am a class A" << std::endl;
    	}
    };
    
    class B : public Base
    {
    public:
    	virtual void Print()
    	{
    		std::cout << "I am a class B" << std::endl;
    	}
    };
    
    Base* foo(Base* obj1, Base* obj2)
    {
    	//if obj1 is an A*, return it
    	if(dynamic_cast<A*>(obj1) != NULL)
    		return obj1;
    	//it doesn't matter if obj2 is an A* or B*
    	//we have to return something
    	return obj2;
    }
    
    int main()
    {
    	A a;
    	B b;
    	foo(&a,&a)->Print();
    	foo(&a,&b)->Print();
    	foo(&b,&a)->Print();
    	foo(&b,&b)->Print();
    	return 0;
    }
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  8. #8
    Registered User
    Join Date
    Jul 2005
    Posts
    14
    Here is the problem!

    Code:
    int main()
    {
    	A a;
    	B b;
    	foo(&a,&a)->Print();
    	foo(&a,&b)->Print();
    }
    You don't declare a or b, you just get
    Code:
    A* a;
    A* b;
    and you have no idea of wether a and b points to A or B objects.

  9. #9
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    why do you need to know what type they are? as pianorain has shown and as daved has told you, most commonly you never need to know an objects type and when you do the scheme that daved explained usually works well.C++ also supports RTTI which can be used when needed but the overheads are large. To write your function you would return a base* and use two dynamic casts. One to check if param 1 is an A then another if that cast told you param1 was really an A to check if param 2 is an A. something like
    Code:
    base* foo(base* p1,base* p2)
    {
       if (dynamic_cast<A*>(p1) != NULL)
       {
           if(dynamic_cast<A*>(p2) != NULL)
              return new A;
       }
       return new B;
    }
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  10. #10
    Fish
    Join Date
    Jul 2005
    Location
    San Diego
    Posts
    6

    maybe?

    if you can make foo a member function with one param instead of a non-member function with two params, you can take advantage of polymorphism to get the right type of object instantiated. Please excuse the psuedo-code.

    Code:
    class A : public C
    {
        C *foo(A& a) { return new A; }
        C *foo(B& b) { return new B; }
    }
    
    class B : public C
    {
        C *foo(C& c) { return new B; }
    }

  11. #11
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Assuming you don't want to make use of a construct based on dynamic_cast<>, the solution to the original problem is to use the visitor pattern. You'll find information on that pattern quite readily using google.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 05-18-2003, 06:29 PM
  2. Replies: 1
    Last Post: 01-10-2003, 10:08 PM
  3. What A Difference 30 Years Make...
    By -dcx- in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 10-18-2002, 06:38 PM
  4. gmake or make, what's the difference?
    By Hubas in forum C++ Programming
    Replies: 0
    Last Post: 02-13-2002, 04:42 AM
  5. Control Classes
    By Neandrake in forum Windows Programming
    Replies: 6
    Last Post: 12-25-2001, 08:01 PM