954,487 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

using pointers

I have a Class Personnel and a sub-class Student
how could i change a pointer pointing to Personnel and have it point to Student?

I'm trying this

Personnel *person=NULL;
    PersonnelNode *node=NULL;
    PersonnelNode *temp, *prev;
    Student *s=new Student();
         while (temp != NULL) {
         person = temp->getNode();
         if (stricmp(name,name)==0){
                prev = temp;
                temp = temp->getNext();
                index++;
            }
         else{
            cout <<"Person to delete is found at index" << index<<endl;
            display_node(person, index);
            s=person;
            s->bookQueue->enqueue(title, due);
            }
         
         }


but it says as an error

error C2440: '=' : cannot convert from 'Personnel *' to 'Student *'

vladdy19
Newbie Poster
20 posts since Jun 2007
Reputation Points: 10
Solved Threads: 0
 

Objects of type Personnel can not be converted to PersonnelNode because it knows nothing about the data and methods of the child class. Its a matter of inherentence -- PersonnelNode inherits from Personnel, not the other way around.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 
how could i change a pointer pointing to Personnel and have it point to Student?


You can typecast it.

s = (Student*)person;
Hamrick
Posting Whiz
325 posts since Jun 2007
Reputation Points: 180
Solved Threads: 34
 

A pointer pointing to base class can be converted to a pointer pointing to derived class (down-casting) if the original pointer is actually pointing to a derived class type.
To enforce this is the work of dynamic_cast operator.

Consider following example.

#include <iostream>

using namespace std;

class base
{
public:
    virtual ~base() {cout << "Inside ~base()" << endl ;}
    virtual void some_function() {cout << "Inside base::some_function()" << endl ;}
};

class derived : public base
{
public:
    ~derived() {cout << "Inside ~derived()" << endl ;}
    void some_function() {cout << "Inside derived::some_function()" << endl ;}
    void special_function() {cout << "Inside derived::special_function()" << endl ;}
};

void free_function( base *pb )
{
    pb->some_function() ;
    //special case, when we need to do something with derived class..
    //example of bad OOD. :)
    derived *converted_pd = dynamic_cast< derived* > ( pb ) ;
    if( 0 != converted_pd )
        converted_pd->special_function() ;
    else
        cout << "dynamic_cast returned NULL. pb was NOT pointing to an obj of type derived." << endl ;
}

int main()
{
    derived *pd = new derived() ;
    base *pb = new base() ;
    base *converted_pb = dynamic_cast<base*>( pd ) ;

    cout << "Calling free_function() with converted_pb." << endl ;
    free_function(converted_pb) ;

    cout << "Calling free_function() with pb." << endl ;
    free_function(pb) ;

    return 0 ;
}

Here is my output:
Calling free_function() with converted_pb.
Inside derived::some_function()
Inside derived::special_function()
Calling free_function() with pb.
Inside base::some_function()
dynamic_cast returned NULL. pb was NOT pointing to an obj of type derived.

Press ENTER to continue.Objects of type Personnel can not be converted to PersonnelNode I think it's a typo?? If not it's correct but irrelevant.

thekashyap
Practically a Posting Shark
811 posts since Feb 2007
Reputation Points: 254
Solved Threads: 75
 

You can typecast it.

s = (Student*)person;

One shouldn't do this in C++. Use C++ style casting instead (of C-style)

thekashyap
Practically a Posting Shark
811 posts since Feb 2007
Reputation Points: 254
Solved Threads: 75
 
Use C++ style casting instead (of C-style)


Why? They do the same thing. And C++ typecasts are too long.

Hamrick
Posting Whiz
325 posts since Jun 2007
Reputation Points: 180
Solved Threads: 34
 
Why? They do the same thing. And C++ typecasts are too long.

In very gentle words NO.
Output of this code:

#include <iostream>

using namespace std;

class base
{
public:
    virtual ~base() {cout << "Inside ~base()" << endl ;}
    virtual void some_function() {cout << "Inside base::some_function()" << endl ;}
};

class derived : public base
{
public:
    ~derived() {cout << "Inside ~derived()" << endl ;}
    void some_function() {cout << "Inside derived::some_function()" << endl ;}
    void special_function() {cout << "Inside derived::special_function()" << endl ;}
};

void free_function( base *pb )
{
    pb->some_function() ;
    //special case, when we need to do something with derived class..
    //example of bad OOD. :)
    derived *converted_pd = dynamic_cast< derived* > ( pb ) ;
    if( 0 != converted_pd )
        converted_pd->special_function() ;
    else
        cout << "dynamic_cast returned NULL. pb was NOT pointing to an obj of type derived." << endl ;

    cout << endl << "Doing C-style casting" << endl ;
    converted_pd = (derived*) pb ;
    if( 0 != converted_pd )
        converted_pd->special_function() ;
    else
        cout << "C-style cast returned NULL. pb was NOT pointing to an obj of type derived." << endl ;
}

int main()
{
    derived *pd = new derived() ;
    base *pb = new base() ;
    base *converted_pb = dynamic_cast<base*>( pd ) ;

    cout << endl << "Calling free_function() with converted_pb." << endl ;
    free_function(converted_pb) ;

    cout << endl << "Calling free_function() with pb." << endl ;
    free_function(pb) ;

    return 0 ;
}

is this:
-----------
Calling free_function() with converted_pb.
Inside derived::some_function()
Inside derived::special_function()

Doing C-style casting
Inside derived::special_function()Calling free_function() with pb.
Inside base::some_function()
dynamic_cast returned NULL. pb was NOT pointing to an obj of type derived.

Doing C-style casting
Inside derived::special_function()

Press ENTER to continue.
-----------
There is your difference and I'm sure you understand the problems associated with it. If not I will explain.

thekashyap
Practically a Posting Shark
811 posts since Feb 2007
Reputation Points: 254
Solved Threads: 75
 

If you know that the conversion works, it doesn't matter, right? If you don't know, you shouldn't be trying to typecast anyway. :)

Hamrick
Posting Whiz
325 posts since Jun 2007
Reputation Points: 180
Solved Threads: 34
 
If you know that the conversion works, it doesn't matter, right?

Now that's perfect question to be answered with someone's signature (I really searched for it and couldn't find) which goes something like:
"Although it might be possible to collect the twigs using your nose, it doesn't necessarily mean it's the best way."
I'm assuming you didn't see the problem.
------------------------------------------
Calling free_function() with pb. => Remember pb points to object of type base, which does not implement a function named special_function().

Inside base::some_function()
dynamic_cast returned NULL. pb was NOT pointing to an obj of type derived. => dynamic_cast knows that pb can not and must not be converted to derived*, so it returns NULL.

Doing C-style casting
Inside derived::special_function() => Even though this object does not have this function a call to it is successful. This is only bad-luck.
------------------------------------------
Now if you still doesn't see the problem, let me give you another one:

#include <iostream>

using namespace std;

enum ActionEnum { GET_LAN_STATUS,
        SHUTDOWN_LAN
     } ;

class employee
{
public:
    employee(const string nameStr):name(nameStr) {}
    virtual ~employee() {cout << "Inside ~employee()" << endl ;}
    virtual void get_status_of_office_LAN() {cout << "get_status_of_office_LAN() by: " << name.c_str() << endl ;}
    string getname() { return name ; }
protected:
    string name ;
};

class administrator : public employee
{
public:
    administrator(const string nameStr):employee(nameStr) {}
    ~administrator() {cout << "Inside ~administrator()" << endl ;}
    void get_status_of_office_LAN() {cout << "get_status_of_office_LAN() by: " << name.c_str() << endl ;}
    void shutdown_office_LAN() {cout << "LAN shutdown by: " << name.c_str() << endl ;}
};

void perform_action( employee *pb, ActionEnum action )
{
    switch( action )
    {
        case GET_LAN_STATUS:
        {
            pb->get_status_of_office_LAN() ;
            break ;
        }

        case SHUTDOWN_LAN:
        {
            administrator *converted_pd = dynamic_cast< administrator* > ( pb ) ;
            if( 0 != converted_pd )
                converted_pd->shutdown_office_LAN() ;
            else
                cout << pb->getname().c_str() << ": does not have required rights to shutdown LAN." << endl ;

            cout << endl << "Doing C-style casting" << endl ;
            converted_pd = (administrator*) pb ;
            if( 0 != converted_pd )
                converted_pd->shutdown_office_LAN() ;
            else
                cout << pb->getname().c_str() << ": does not have required rights to shutdown LAN." << endl ;
        }
        default: break;
    }
}

int main()
{
    administrator *pd = new administrator("Some administrator") ;
    employee *pb = new employee("NOT an administrator") ;

    cout << endl << "Calling perform_action(GET_LAN_STATUS) with pb." << endl ;
    perform_action(pb, GET_LAN_STATUS) ;
    cout << endl << "Calling perform_action(SHUTDOWN_LAN) with pb." << endl ;
    perform_action(pb, SHUTDOWN_LAN) ;

    return 0 ;
}

and here is the output:
----------------------------------------------------------
Calling perform_action(GET_LAN_STATUS) with pb.
get_status_of_office_LAN() by: NOT an administrator

Calling perform_action(SHUTDOWN_LAN) with pb.
NOT an administrator: does not have required rights to shutdown LAN.

Doing C-style castingLAN shutdown by: NOT an administrator

Press ENTER to continue.
----------------------------------------------------------

thekashyap
Practically a Posting Shark
811 posts since Feb 2007
Reputation Points: 254
Solved Threads: 75
 

Oh. Okay. :$

Hamrick
Posting Whiz
325 posts since Jun 2007
Reputation Points: 180
Solved Threads: 34
 

> Now that's perfect question to be answered with someone's signature
:-)

Just because it is possible to push twigs along the ground with one’s nose does not necessarily mean that that is the best way to collect firewood.
~s.o.s~
Failure as a human
Administrator
11,938 posts since Jun 2006
Reputation Points: 3,281
Solved Threads: 734
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You