Person *p = new Teacher("Bob Sagat", "555-55-5555", 6, 20000.0); p.printInfo(); Call Person::printInfo(), not Teacher::printInfo(). What we want is the ability to call the function associated with whatever the object instance is, not necessarily the type of the variable. Solution: Use virtual functions. class Person { public: Person(); Person(string theName, string theSSN); string getName() const; string getSSN() const; void setName(string newName); void setSSN(string newSSN); virtual void printInfo() const; private: string name; string ssn; }; Now, any class that inherits from person will also have a virtual printInfo function, even if you don't declare it as such. You should still do so for clarity-sake. Now when we do Person *p = new Teacher("Bob Sagat", "555-55-5555", 6, 20000.0); p->printInfo(); // Calls Teacher::printInfo; p = new Staff("Billy Joe", "444-44-4444", 12, 40, 20.0); p->printInfo(); // Calls Staff::printInfo; Calls whatever p actually points to at the time. From above, it is possible for the compiler to know at compile-time which one to call, but this will still work when it is not known such as here: void printPerson(Person& p) { p.printInfo(); } Teacher t("Bob Sagat", "555-55-5555", 6, 20000.0); Staff s("Billy Joe", "444-44-4444", 12, 40, 20.0); printPerson(t); // calls Teacher::printInfo printPerson(s); // calls Staff::printInfo With virtual functions, the program actually chooses which function to call at run-time, while the program is running. Remember our dilemma with what Person::printInfo() should do because nobody should be instantiating a Person. We can actually prevent instantiation by using pure virtual functions. class Person { public: Person(); Person(string theName, string theSSN); string getName() const; string getSSN() const; void setName(string newName); void setSSN(string newSSN); virtual void printInfo() const = 0; private: string name; string ssn; }; Now, we don't even have to define Person::printInfo(), and if someone tries to instantiate a Person, it will give a compile-time error, because Person isn't really complete; all its function aren't defined. When we want a child class to be able to be instantiated, we must define all pure virtual functions. Classes that have at least one pure virtual functions are called 'Abstract'. Using virtual functions, we can make a LinkedList class that holds any Person. class LinkedList { private: struct LinkedListNode { Person *p; LinkedListNode *next; }; LinkedListNode *head; LinkedListNode *tail; public: LinkedList(); ~LinkedList(); void add(Person *p); Person* removeByName(string name); bool empty() const; void printList() const; }; LinkedList::LinkedList() { head = NULL; tail = NULL; } LinkedList::~LinkedList() { LinkedListNode *cur, *tmp; for(cur = head; cur; cur = tmp) { tmp = cur->next; delete cur; } } void LinkedList::add(Person *p) { LinkedListNode *n = new LinkedListNode; n->p = p; n->next = NULL; if(tail != NULL) { tail->next = n; } tail = n; if(head == NULL) { head = n; } } Person* LinkedList::removeByName(string name) { LinkedListNode *cur; LinkedListNode *prev = NULL; for(cur = head; cur; cur = cur->next) { if(cur->p->name == name) { Person *p = cur->p; if(cur == head) { head = cur->next; } if(cur == tail) { tail = prev; } if(prev) { prev->next = cur->next; } delete cur; return p; } prev = cur; } return NULL; } bool LinkedList::empty() const { return head == NULL ? true : false; } void printList() const { LinkedListNode *cur; for(cur = head; cur; cur = cur->next) { cur->p->printInfo(); } } int main() { LinkedList l; l.add(new Teacher("Bob Sagat", "555-55-5555", 6, 20000.0)); l.add(new Staff("Billy Joe", "444-44-4444", 12, 40, 20.0)); l.add(new Student("John Doe", "333-33-3333", 3)); l.printList(); // will call the appropriate printInfo for the type }