Link to home
Start Free TrialLog in
Avatar of b_vishwajit
b_vishwajit

asked on

Vritual functions casting from base class to derived class (Easy for experienced programmers)

This is the structure of my program:

class A
{
             private:
                         //some private fields here.
             public:
                        //constructors
                       //some functions
                       virtual void printObj();


}

//define printObj() here

class B:public class A //public inheritance
{
          private:
                          //instance varibales.
          public:
                       //
                        void printObj();
}


main()
{
              A arrayOFA[size];

                if(type A)
                {
                         //call the parent virtual function
                 }
                 else if(type B)
                {
                         //call virtual function from child class
                         //I have problems here
                 }
                   
}


In my main program I am giving the user option to enter an object of Type A or B into the array. I then just assign object of type b to an array position. B has some extra private members other than parent class. Hence printObj() function is slightly different for class B.

Now I have flags to determine what kind of object an array position holds. Then after checking the flag I just want to call the appropriate printObj() function. If the object is of type A then I have no problems calling the parent class function. But if its of type
B how do it? I tried to use static_cast and tried to cast the object in the array to type B (i.e. parent to child class casting). But I got some weird errors. Whats the appropriate way to do it? Any good experts around here.............
Thanks in advance.
SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If you have an array of concrete types, you can't call a derive type from it.

 A arrayOFA[size]; //This is an array of concrete types

If you want to have derive types in your array, then you need to create an array of pointers to your base type.
Avatar of b_vishwajit
b_vishwajit

ASKER

What do you mean by concrete types?
It is an array of type A and I am inserting type B which is of type A into the array. So when I want to retrieve B from the array how do I do it? Is there no way of doing this without using pointers?

A arrayOFA[size];

vector<A*> MyArrayOfPointersTo_A_Types;

i               f(type A)
               {
                        //create A type
                        MyArrayOfPointersTo_A_Types.push_back(new A());
                }
                else if(type B)
               {
                        //create B type
                        MyArrayOfPointersTo_A_Types.push_back(new B());
                }

//Later in your code, you don't have to check what type you have.
Just call the member function, and it will select the right derive member function.
MyArrayOfPointersTo_A_Types[0]->printObj(); //Will print correct member function.


ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> What do you mean by concrete types?

May I ask why you are not giving any reaction to my post?
jkr I will try your solution and get back to you. It looks like it makes sense.
Example code:

class A
{
public:
      A(int x):m_x(x){}
      virtual int GetData(){return m_x;}
protected:
      int m_x;
};
class B : public A
{
public:
      B(int x, int y):A(x), m_y(y){}
      int GetData(){return m_x + m_y;}
private:
      int m_y;
};
 
int main(int argc, char* argv[])
{
      B b(1, 2);
      A a1 = b;//This compiles, but a loose properties of b
      cout << a1.GetData() << endl;

      A *a2 = new B(3, 4);//Compiles and retains properties of B
      cout << a2->GetData() << endl;

      // A a3 = new B(3, 4);//Does not compile

      
      return 0;
}
jkr. Though your solution looks conceptualy correct in my program pb->printObj(); still invokes the printObj() from the parent class.
Why is that? You should note this while adding type B to array of type A I am not doing any type casting. Type B can be added to array of type A without any problems since type B is of type A(inheritance). But while doing that am I loosing member fields of type  B. I think I should not. What do you say? Reply ASAP.
You'll notice that a2->GetData() calls the correct function.
You don't need to determine what type you have for this to work.
That's how virtual functions should be used.
B* pb = (B*) &arrayOFA[someindex];

The above is not portable for concrete types, and will result in undefined behavior at best.
>>A a1 = b;//This compiles, but a loose properties of b
Yup. I was thinking exactly the same way. So I cannot avoid pointers in any manner..
Example code for your requirements:
class A
{
public:
      A(int x):m_x(x){}
      virtual int GetData(){return m_x;}
protected:
      int m_x;
};
class B : public A
{
public:
      B(int x, int y):A(x), m_y(y){}
      int GetData(){return m_x + m_y;}
private:
      int m_y;
};
 
int main(int argc, char* argv[])
{
      vector<A*> arrayOFA;
      arrayOFA.push_back(new A(1));
      arrayOFA.push_back(new B(1, 3));

      cout << arrayOFA[0]->GetData() << endl;
      cout << arrayOFA[1]->GetData() << endl;
>>Yup. I was thinking exactly the same way. So I cannot avoid pointers in any manner..

Not for this requirement.
You have to use pointers to access derive type virtual functions from a base type.
I was trying to do this within a switch statement:
A* aPtr=new B(args); I got the following error from the compiler:
crosses initialization of `StudentRecord*srPtr'
crosses initialization of `A* aPtr'

What the heck is that supposed to mean?
>>crosses initialization of `StudentRecord*srPtr'//Ignore this line.

//Actual error

 jump to case label

crosses initialization of `A* aPtr'
Are you sure your B class is derived from A class?
And does your B class take the args type?
Ned to see more code.
Anyway I have an array of type A in my program and I want to stick with it. Doe anyone have any solution for this problem?
I will have to change my whole program structure if use array of pointers. I dont want to do it.
Are you sure your B class is derived from A class?
And does your B class take the args type?
Yes.

In my program I have 4 classes in total. If post my code here its all gonna be messy and I dont want to do that.
Can you uploaded to a website?
I can do that but it will be there only for 10 to 15 minutes. Just check the thread after 2 or three minutes. I will post the link here.
You can create an array of pointers without using vector.

Example:
int main(int argc, char* argv[])
{
      A* arrayOFA[2] = {0};
      arrayOFA[0] = new A(1);
      arrayOFA[1] = new B(1, 3);

      cout << arrayOFA[0]->GetData() << endl;
      cout << arrayOFA[1]->GetData() << endl;
Just do it quickly.
http://www.ug.cs.sunysb.edu/~bhadrasv/
Download the "tmpsrc" folder. I cant keep it  there for a long time.
Axter I know I can do that. But I will have to redesign my whole program all over again. Is there any way of doing it just using an array of type A objects. Thanks.
>>using an array of type A objects
No
Let me know when you  r done downloading. I have to remove it.
Ok I willl follow up on this 2mmorrow. I will decide whehther I want to use an array of pointers (probably I am not gonna do that).
Thanks any way Axter for trying.
Sorry, I just got back.

I'll be here for about 15 more minutes if you want to put it backup again.
Sorry for the delay. I was just not paying attention for a while.