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 *'

Recommended Answers

All 10 Replies

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.

how could i change a pointer pointing to Personnel and have it point to Student?

You can typecast it.

s = (Student*)person;

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.

You can typecast it.

s = (Student*)person;

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

Use C++ style casting instead (of C-style)

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

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.

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. :)

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 casting
LAN shutdown by: NOT an administrator

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

commented: Good job. +13

Oh. Okay. :$

> 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.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.