Reputation: 1279
I understood why a base class pointer is made to point to a derived class object. But, I fail to understand why we need to assign to it, a base class object, when it is a base class object by itself.
Can anyone please explain that?
#include <iostream>
using namespace std;
class base {
public:
virtual void vfunc() {
cout << "This is base's vfunc().\n";
}
};
class derived1 : public base {
public:
void vfunc() {
cout << "This is derived1's vfunc().\n";
}
};
int main()
{
base *p, b;
derived1 d1;
// point to base
p = &b;
p->vfunc(); // access base's vfunc()
// point to derived1
p = &d1;
p->vfunc(); // access derived1's vfunc()
return 0;
}
Upvotes: 3
Views: 5985
Reputation: 1
This type of referencing is very well applied when you want to apply design patterns, (you may need to pass an advanced course of object oriented design, or start by reading book: head first, design patters, i suggest)
see for example how to implement a decorator pattern in java in the mentioned book.
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
then think we have espresso and DarkRoast as two child classes:
public class Espresso extends Beverage {
public Espresso() {
this.description = "Espresso";
}
public double cost() {
return 1.99;
}
}
public class DarkRoast extends Beverage {
public DarkRoast() {
description = "Dark Roast Coffee";
}
public double cost() {
return .99;
}
}
now, we are going to add decorator:
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
and build some concrete decorator:
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public double cost() {
return .20 + beverage.cost();
}
}
and another wrapper:
public class Whip extends CondimentDecorator {
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public double cost() {
return .10 + beverage.cost();
}
}
finally, see what happened in the main function and how we take advantages of the pointer to the father class:
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
can you guess what is the output? well:
Espresso $1.99
Dark Roast Coffee, Mocha, Mocha, Whip $1.49
Upvotes: -2
Reputation: 4663
It is not mandatory to call
p = &b;
p->vFunc();
you can directly call
b.vFunc();
both will give you the same result.
However it seems you should understand the power of virtual functions. Assume if you want to store 10 instances of either base
or derived1
objects and call the function repeatedly, how will you do that? or after storing it in an array if you want to pass it to a common function?
vase *p[4];
base b1;
derived d;
p[0] = new base();
p[1] = &b1;
p[2] = new dervied1();
p[3] = &d;
for (int i =0 ;i <4 ;i++)
{
p[i]->vFunc();
}
Upvotes: 1
Reputation: 490048
I'm not entirely sure I understand your question perfectly, but a typical case of using a virtual function is when we write a function, and want it to work with an object of the base class or anything derived from it:
struct base {
virtual void dosomething() = 0;
};
void myfunc(base *b) {
b->dosomething();
}
When we write myfunc
, we neither know nor care about the exact identity of the object involved -- we just care about the fact that it knows how to dosomething
on command.
As far as writing code like you've shown, where we directly assign the addresses of objects of base or derived class to a pointer, that's more the exception than the rule. You're quite right that in this sort of situation, we don't really gain a lot from using a pointer to base to refer to an object of derived. The main benefit is from something like a function where the derived class may not even exist yet when we write the code, but as long as the derived class conforms to the prescribed interface, it'll work.
Upvotes: 1
Reputation: 206508
Because pointers by themselves cannot do anything.
A pointer has to point to a valid object so that you can make any use of it.
Why the above statement?
A step by step explanation will perhaps clear your doubt.
Step 1:
base *p;
Creates a pointer p
which can store the address of an object of class base
. But it is not initialized it points to any random address in memory.
Step 2:
p = &b;
Assigns the address of an valid base
object to the pointer p
. p
now contains the address of this object.
Step 3:
p->vfunc(); // access base's vfunc()
Dererences the pointer p
and Calls the method vfunc()
on the object pointed by it. i.e: b
.
If you remove the Step 2:, Your code just tries to Dereference a Uninitialized pointer and would cause a Undefined Behavior & most likely a crash.
Upvotes: 3