Polymorphism and Dynamic Binding

I am trying to write a program in which a function can take objects of different classes with common parents. Depending on which class it belongs to, the function will act differently. The problem is telling the compiler to determine the class at run-time and act accordingly.

Here is an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;

class Parent{
   public:
      virtual void stateClass(){ cout << "Parent";};
};

class Child_1 : public Parent{
   public:
      void stateClass(){ cout << "Child_1";};
};

class Child_2 : public Parent{
   public:
      void stateClass(){ cout << "Child_2";};
};

void dynamic_stateClass(Parent object){ object.stateClass(); } // This is the key part of the question:
// object should either be of Child_1 or Child_2, however this returns Parent.stateClass()

int main(){
   Child_1 object1;
   Child_2 object2;

   dynamic_stateClass(object1);  // Again, both of these should output their
   dynamic_stateClass(object2);  //  respective classes, but they output "Parent"


How would one make a function such as "dynamic_stateClass()" which can take objects of different classes with common parents?
Last edited on
make following changes:
#include <iostream>
using namespace std;

class Parent{
public:
virtual void stateClass(){ cout << "Parent";};
};

class Child_1 : public Parent{
public:
void stateClass()
{ Parent:: stateClass();
cout << "Child_1";};
};

class Child_2 : public Parent{
public:
void stateClass()
{ Parent:: stateClass();
cout << "Child_2";};
};

void dynamic_stateClass(Parent *object){ object->stateClass(); }
int main(){
Child_1 object1;
Child_2 object2;

dynamic_stateClass(&object1);
dynamic_stateClass(&object2);
}
I think this will give u ur desired output.
closed account (D80DSL3A)
It also works if you pass by reference.
void dynamic_stateClass(Parent& object){ object.stateClass(); }
All other code stays the same.
Thanks! That worked... I'm not sure how the pointer fixes things though.
Is there any explanation for that?
@arjita07
I do not know why you are suggesting some of those changes (or why you are not using [code] tags).

@Wildebai
Polymorphism only works when references are involved (via either a pointer type or a reference type).

Your function dynamic_stateClass() currently takes an explicit type of Parent. Hence, everything inside the function thinks you are working with a Parent -- there is no polymorphism involved.

1
2
3
void dynamic_stateClass(Parent object) {
   object.stateClass();  // 'object' is a Parent (even if it isn't really), so I'll call Parent::stateClass()
}

In order to use the polymorphism, you need to use a proper reference.

1
2
3
void dynamic_stateClass(Pointer* object) {  // via a pointer type  
   object->stateClass();
}
1
2
3
void dynamic_stateClass(Pointer& object) {  // via a reference type
   object.stateClass();
}

BTW, you should be aware that the word "state" has meaning in CS other than what you are using it for. You should use the word "print" or "tell" instead. (In CS, the word "state" is typically understood as, in very simple terms, "the state of things".)

Hope this helps.
The function dynamic_stateClass() doesn't just think it's working with a Parent - it is! When you have a function parameter, the value you are passing in is copied, and this is done by invoking the copy constructor of the class that is the param type. So in this case, you are constructing a new object of type Parent, using Parent's copy constructor Parent::Parent(const Parent &) (which can accept a 'const Child_1 &' as well).
I am wondering whether I should have posted the file I am trying to work this principle into... since the example is (slightly) diverging from the original purpose (at least to my simple mind).

Here is the code I am working with, the functions that require polymorphism of this sort are LinkCell::LinkCell and LinkCell::flow

The program I am trying to write is a program that can simulate a flowchart.
A flowchart is made of "cells", which are connected by "yes"/"no".
I divide cells into to types "Link" and "End", where Link cells connect to other cells when answered, and End cells output a final message before exiting.

Here is the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <string>

using namespace std;
        
class Cell {
   protected:
        string query;
	string val;
   public:
        void setVal();
        string getVal() {return val;}
        string getQuery() {return query;}
    virtual void flow(){cout << "*** Error: accessed Cell.flow() \n";};
   };
 
void Cell::setVal(){
      cout << getQuery() << " [y/n] ";
      cin >> val;
      if ((getVal()!="y") && (getVal()!="n")){
         while ((getVal()!="y")&&(getVal()!="n")){
            cout << "Please enter y or n: ";
            cin >> val;
         }
      }
}

class LinkCell: public Cell {
	Cell yQuery;
	Cell nQuery;
   public:
	LinkCell(string,Cell&,Cell&);
	void flow();
};

LinkCell::LinkCell (string setQuery, Cell yLink, Cell nLink) {
	query = setQuery;
	yQuery = yLink;
	nQuery = nLink;
}

void LinkCell::flow(){
	cout << "--> Reached setVal for LinkCell " << getQuery() << endl; setVal();
        if (getVal()=="y"){cout << "==> Reached getVal=y : atttemping to execute yQuery '" << yQuery.getQuery() << "'" << endl; yQuery.flow();}
        if (getVal()=="n"){cout << "==> Reached getVal=n : atttemping to execute nQuery '" << nQuery.getQuery() << "'" << endl; nQuery.flow();}
}

class EndCell: public Cell {
	string yEnd;
	string nEnd;
   public:
	EndCell(string,string,string);
    void flow();
};

EndCell::EndCell (string setQuery, string yMessage, string nMessage){
	query = setQuery;
	yEnd = yMessage;
	nEnd = nMessage;
}


void EndCell::flow(){
	setVal();
    if (getVal()=="y"){cout << yEnd << endl;}
    if (getVal()=="n"){cout << nEnd << endl;}
}

int main(){

	EndCell sorry("Do you want me to feel sorry for you?","I'm sorry for you","I'm not sorry for you");
	EndCell happy("Do you want me to feel happy for you?","I'm happy for you","I'm not happy for you");
	EndCell work("Do you want to work now?","Let's do it!","Let's hang out");
	LinkCell help("Can I help you?",work,sorry);
	LinkCell ok("Are you ok?",happy,help);

	ok.flow();

return 0;
}


main() is an example usage of the class structure.

Edit: changed code to (implementing Duaos' solution – thanks):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <string>

using namespace std;
        
class Cell {
   protected:
        string query;
	string val;
   public:
        void setVal();
        string getVal() {return val;}
        string getQuery() {return query;}
    virtual void flow(){cout << "*** Error: accessed Cell.flow() \n";};
   };
 
void Cell::setVal(){
      cout << getQuery() << " [y/n] ";
      cin >> val;
      if ((getVal()!="y") && (getVal()!="n")){
         while ((getVal()!="y")&&(getVal()!="n")){
            cout << "Please enter y or n: ";
            cin >> val;
         }
      }
}

class LinkCell: public Cell {
	Cell *yQuery;
	Cell *nQuery;
   public:
	LinkCell(string,Cell*,Cell*);
	void flow();
};

LinkCell::LinkCell (string setQuery, Cell *yLink, Cell *nLink) {
	query = setQuery;
	*yQuery = *yLink;
	*nQuery = *nLink;
}

void LinkCell::flow(){
	cout << "--> Reached setVal for LinkCell " << getQuery() << endl; setVal();
        if (getVal()=="y"){cout << "==> Reached getVal=y : atttemping to execute yQuery '" << yQuery->getQuery() << "'" << endl; yQuery->flow();}
        if (getVal()=="n"){cout << "==> Reached getVal=n : atttemping to execute nQuery '" << nQuery->getQuery() << "'" << endl; nQuery->flow();}
}

class EndCell: public Cell {
	string yEnd;
	string nEnd;
   public:
	EndCell(string,string,string);
    void flow();
};

EndCell::EndCell (string setQuery, string yMessage, string nMessage){
	query = setQuery;
	yEnd = yMessage;
	nEnd = nMessage;
}


void EndCell::flow(){
	setVal();
    if (getVal()=="y"){cout << yEnd << endl;}
    if (getVal()=="n"){cout << nEnd << endl;}
}

int main(){

	EndCell sorry("Do you want me to feel sorry for you?","I'm sorry for you","I'm not sorry for you");
	EndCell happy("Do you want me to feel happy for you?","I'm happy for you","I'm not happy for you");
	EndCell work("Do you want to work now?","Let's do it!","Let's hang out");
	LinkCell help("Can I help you?",&work,&sorry);
	LinkCell ok("Are you ok?",&happy,&help);

	ok.flow();

return 0;
}


This gives a segmentation fault 11, but the polymorphism question is answered... marking as solved
Last edited on
Topic archived. No new replies allowed.