A question related to virtual function

B

babu

class CPrintString
{
void printName(Person* p)
{
printf("person");
}

void printName(Student * s)
{
printf("student");
}
};

Here, Person is the base class of Student. Now if we write -

Person * st = new Student();
CPrintString * pr =new CPrintString();
pr->printName(st);

The output is "person". But we need "student" to be printed. Why such
thing occurs?

Now What is the solution so that the correct function is called at
runtime based on the parameter object type, so that "student" can be
printed in the previous calling sequence? Is there any solution
without changing class CPrintString? If exists please give.

Thanks
Babu
 
I

Invincible

Hi,
If one function is declared Virtual in Base class and derived class
has the implementation for that, then you can call derived version of
function as you had shown by using base class pointer ( Person * st ):

But in this case Base class pointer(Person * ) would be passed to
printName() as calling to printname is through CPrintString* . If you
really want to print "Student" then derive CPrintString from Person
class and make printName() to be virtual there.

~Vinay
 
B

babu

Hi,
If one function is declared Virtual in Base class and derived class
has the implementation for that, then you can call derived version of
function as you had shown by using base class pointer ( Person * st ):

But in this case Base class pointer(Person * ) would be passed to
printName() as calling to printname is through CPrintString* . If you
really want to print "Student" then derive CPrintString from Person
class and make printName() to be virtual there.

~Vinay

But can I find any solution without changing the class CPrintSting?
 
X

xsws5638

But can I find any solution without changing the class CPrintSting?
I think it does not exist a solution without changing CPrintString.
From the OO object, I sugest you make printName as Person's virtual
function. Because printName closely belongs to Person class!
 
I

Invincible

But can I find any solution without changing the class CPrintSting?

I dont think It would be possible to get solution without changing
CPrintSting. You want behavior of polymorphism so u have to abide by
the rules of it.
 
S

Salt_Peter

class CPrintString
{
void printName(Person* p)
{
printf("person");
}

void printName(Student * s)
{
printf("student");
}

};

Here, Person is the base class of Student. Now if we write -

Person * st = new Student();
CPrintString * pr =new CPrintString();
pr->printName(st);

The output is "person". But we need "student" to be printed. Why such
thing occurs?

Now What is the solution so that the correct function is called at
runtime based on the parameter object type, so that "student" can be
printed in the previous calling sequence? Is there any solution
without changing class CPrintString? If exists please give.

Thanks
Babu


CPrintString should not be a class unless its purpose is akin to a
printer.
Make it a function instead.
If its purpose was to be a printer, its purpose in life is not to
detect *what* type of Person is being passed to it. Let the Person
object determine that.
The printer doesn't care.

#include <iostream>
#include <string>

class Person
{
std::string m_s;
public:
Person()
: m_s("person") { }
Person(const std::string s)
: m_s(s) { }
std::string getString() const
{
return m_s;
}
};

class Student : public Person
{
public:
Student()
: Person("student") { }
};

struct CPrintString
{
void printName(const Person& r_p)
{
std::cout << r_p.getString();
std::cout << std::endl;
}
};

int main()
{
Student student;
CPrintString printer;
printer.printName(student);
}

This way, if you add another type of Person or Student to your
project, the printer is unaffected. Note: pointers replaced by const
references.
 
B

babu

I dont think It would be possible to get solution without changing
CPrintSting. You want behavior of polymorphism so u have to abide by
the rules of it.

I think If I type cast in calling pr->printName(st) then I can find
solution. In that case callin may be pr->printName((Student *)st)
 
I

Ian Collins

babu said:
I think If I type cast in calling pr->printName(st) then I can find
solution. In that case callin may be pr->printName((Student *)st)
It's "cast", not "type cast".

If you know it's a Student, why not declare it as one? If you don't
(hence the base pointer), how do you know what to cast to? If you are
going to cast, at least use a C++ style cast.
 
K

KarthikSankar.R

You can alternately implement like below.And yes the PrintName should
be virtual
class Person
{
private:

char *m_str;

public:

Person(char *str)
{
m_str=str;
}

virtual void PrintName()
{
cout<<"\nPerson:"<<m_str;
}
};

class Student : public Person
{
private:
char *m_str;
public:
Student(char *str):person(str)
{
m_str=str;
}

virtual void PrintName()
{
cout<<"\nStudent:"<<m_str;
}

};

void main()
{
Person *ptr=new Student("Student");
ptr->PrintName();
Person *ptr1=new Person("Person");
ptr1->PrintName();
}
Output:
Student:Student
Parent:parent

If virtual is not used
Output:
Parent:parent
Parent:parent
 
S

Salt_Peter

You can alternately implement like below.And yes the PrintName should
be virtual
class Person
{
private:

char *m_str;

public:

Person(char *str)
{
m_str=str;
}

virtual void PrintName()
{
cout<<"\nPerson:"<<m_str;
}

};

class Student : public Person
{
private:
char *m_str;
public:
Student(char *str):person(str)
{
m_str=str;
}

virtual void PrintName()
{
cout<<"\nStudent:"<<m_str;
}

};

void main()

int main()
{
Person *ptr=new Student("Student");
ptr->PrintName();
Person *ptr1=new Person("Person");
ptr1->PrintName();}

Output:
Student:Student
Parent:parent

If virtual is not used
Output:
Parent:parent
Parent:parent

This is C++, not Java.
The above is undefined behaviour since you did not provide a required
virtual d~tor in the Person class. Also, any new or new[] without a
corresponding delete or []delete is a memory leak.
You are storing the same pointer in both the derived class and the
base class. Why?.
PrintName() need not be virtual and it should be a const function.
A heap allocation that involves a type with a member pointer to a
literal (char*) is just begging for trouble. Use a std::string, a
std::vector< char > or a primitive char array instead.

Finally: have you ever heard of init lists?

class Person
{
std::string m_s;
public:
Person(std::string s)
:m_s(s) { }
virtual ~Person() { }
void PrintName() const { ... }
};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,294
Messages
2,571,511
Members
48,206
Latest member
EpifaniaMc

Latest Threads

Top