Here in the code i am able to successfully point a derived class pointer to a base class object and I m also able to set and get value of the base class private member. If this is not giving any issues then what is the need of virtual functions and the whole confusion around run time polymorphism/late binding/vtable bla bla bal!!!
#include <iostream>
using namespace std;
class Base
{
int a;
public:
Base(int x=0):a(x){}
void setValueForMember(int p)
{
a=p;
}
void showValueOfMember(){cout<<endl<<a<<endl;}
};
class Derived:public Base
{
int b;
public:
Derived(){}
Derived(int y):b(y){}
void setValueForMember(int q)
{
b=q;
}
void showValueOfMember(){cout<<endl<<b<<endl;}
};
int main()
{
Derived D;
D.setValueForMember(10);
Derived *Dptr = new Derived();
Dptr = &D;
Dptr->showValueOfMember();
Base B;
Dptr = (Derived*)&B;
Dptr->setValueForMember(20);
Dptr->showValueOfMember();
return 0;
}
Virtual function is used in the case when , we want to access the members of the derived class using the pointer of type, base class.
when you will use
Bptr=&D;
you won't be able to access the members of Derived class , except the members inherited from the Base class.
If you want to access the members of the Derived class using the same pointer that is Bptr, you must have to use virtual function,
and at the time of compilation it is decided that which function is going to be executed, that's why it is known as
Run-Time polymorphism or Dynamic Binding
.
Related
class Base1{
public:
Base1(){};
virtual ~Base1() = 0;
}
class Derived1 : public Base1{
public:
Derived1(int a) : a(a){};
~Derived1();
int a;
}
class Base2{
public:
Base2(){};
virtual ~Base2() = 0;
}
class Derived2 : public Base2{
public:
Derived2(int b) : b(b){};
~Derived2();
int b;
void func(const Base1 &base1); // How to access Derived1::a here?
}
Given the above class definition, how can I access Derived1::a in void func(const Base1 &base1)? I am still new to polymorphism. I tried to use different static_cast or dynamic_cast methods but none of them works. What should I do inside the function so I can access a derived class member from a base class reference?
FYI I can't change the class definition for my coursework requirement, and that is what given to me. I understand that it is simpler to just pass Derived1 as parameter but I am not allow to do so.
Given the above class definition, how can I access Derived1::a in void func(const Base1 &base1)? ... FYI I can't change the class definition for my coursework requirement, and that is what given to me.
Ideally, you should expose a virtual method in Base1 that returns an int (or int&), and then have Derived1 override that method to return its a member.
But, given that you are not allowed to change the class definitions, that is not an option.
You need a pointer or reference to a Derived1 object in order to access its a member directly. Which really leaves you with only 1 choice - you can use dynamic_cast to typecast the base class reference to the derived class type, eg:
void Derived2::func(const Base1 &base1)
{
// this will raise an exception if the cast fails at runtime
const Derived1 &d = dynamic_cast<const Derived1&>(base1);
// use d.a as needed...
}
Alternatively:
void Derived2::func(const Base1 &base1)
{
// this will return null if the cast fails at runtime
const Derived1 *d = dynamic_cast<const Derived1*>(&base1);
if (d) {
// use d->a as needed...
} else {
// do something else...
}
}
I have a base class which serves as an interface (if I use that word correctly). The idea is that the base class has some derived classes that implement one virtual function of the base class. Then I also need another class that extends the base class (lets call it extended base). What I would like is that I can store a class derived from base into an extended base pointer.
MWE:
class Base {
public:
virtual ~Base();
virtual double value();
}
class Derived : public Base{
public:
double value() override {return 5;}
}
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase ();
virtual double value2(){return 10;}
}
int main() {
ExtendedBase * object;
object = new Derived();
std::cout << object->value(); //should give implementation in Derived, i.e. 5
std::cout << object->value2(); //should give implementation in ExtendedBase, i.e. 10
delete object;
return 0;
}
With this MWE I get a compile error at the second line in the main. error: cannot convert 'Derived*' to 'ExtendedBase*' in assignment object = new Derived();. Part of me understands why it doesn't work (although I can't explain), but I would like to know if I can get the desired behaviour in some other way.
P.S. Sorry about the bad question name, I couldn't think of another way to keep it short
P.S.2 I know raw pointers like this are not advised. In the future I will change to smart pointers but I don't think they are needed for this simple example
ExtendedBase and Derived are each derived from Base. If you want to use an ExtendedBase* pointer to point to a Derived object, you will need to derive Derived from ExtendedBase.
To use a different example,
class Feline{
virtual void run();
}
class Housecat : Feline{
void run() {}
}
class BigCat : Feline{
virtual void run();
virtual void roar();
}
Here Feline, Housecat, and BigCat are analogous to Base, Derived, and ExtendedBase. BigCat and Housecat are each Feline, but since Housecat is not a BigCat, you can't use a BigCat* pointer to point to a Housecat.
This is the desired behavior from a language architect perspective.
For instance, if you have
class Ship
{
public:
virtual void move() = 0;
}
class Steamboat : public Ship
{
public:
virtual void move() override { ... }
}
class Sailboat : public Ship
{
public:
virtual void move() override { ... }
virtual void setSails() { ... }
}
Now, you don't want a Steamboat to become a Sailboat all of a sudden, hence:
Steamboat* tootoo = new Sailboat;
cannot be valid.
That's why your code cannot work. Conceptually.
So giving a quick fix is not possible, because your concept is not really clear.
When you are assigning an address to a pointer that means you should be able to access all the members of the type the pointer is pointing to through the pointer.
For ex,
class B {};
class D : B {};
B *p = new D();
now through p, at least you can access all the members of base portion of the derived class.
But in your code,
ExtendedBase * object;
object = new Derived();
object should be able to access all the members of ExtendedBase portion of the derived class. But how is it possible as derived class is not derived from ExtendeBase. So compiler is throwing error.
You need to do some changes in your code to work.
To make base as interface (abstract class), you need to define at
least one member function as pure virtual.
If you want to access the member function of ExtendedBase through
Base pointer, you should define same function 'val' in your
ExtendedBase.
Below are the changes.
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {};
virtual double value() = 0;
};
class Derived : public Base{
public:
~Derived() {};
double value() {
return 5;
}
};
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase () {};
double value()
{
return 10;
}
};
int main() {
Base *p = new Derived();
std::cout << p->value() << std::endl;
delete p;
Base *p1 = new ExtendedBase();
std::cout << p1->value() << std::endl;
delete p1;
return 0;
}
If I have a base class and a derived class, such as:
class Base {
protected:
int a;
public:
void setA(int);
void getA(int);
}
class Derived : public Base {
private:
int b;
public:
void doThing();
}
Then a third, additional class that uses the base class:
class OtherClass {
public:
Base doClassThing(Base*, Base*);
}
What's the best way to pass the derived class to a function that's defined to return a base class and take the base class as an argument. Like this:
Derived *x = new Derived();
Derived *y = new Derived();
doClassThing(x, y);
Would I pass the objects with a type cast? Or should I type cast the objects when they're first created?
To answer your two questions:
You would not cast the objects when they're first created.
There is no need to cast when calling; You do not need to modify the code in your question.
I have a base class
class base {
public:
base();
int someData;
virtual void foo(){
std::cout << someData;
}
};
and a few derived classes like
class derived : public base {
public:
derived();
void foo(){
std::cout << someData * 5;
}
};
Basically they have the same kind of data but the operations on this data are different.
I have another class that doesn't need to know the details of my object, all it needs to do is to set data and call the derived foo().
class useData {
public:
useData();
base x;
int do() { x.someData = 5; return x.foo(); }
};
I want "useData" to be as generic as possible so I'm using the base class instead of the derived class in its definition.
Of course in this scenario it will call the base method and not the derived one. How can I rewrite my code or make it automatically (without type checking or similar) call the derived method?
Thank you
To use polymorphism you need some pointer or references. So in useData the variable x should be declared as a base *. Afterward, you can create is using a new with any derived class. Polymorphism will perform as expected..
I have following
class base
{
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};
now I have
base* pbase = new derived();
pbase->myFunc();
I am getting error myFunc is not a member function of base.
How to avoid this? and how to make myFunc get called?
Note I should have base class contain no function as it is part of design and above code is part of big function
If you are adamant that this function should NOT be a part of base, you have but 2 options to do it.
Either use a pointer to derived class
derived* pDerived = new derived();
pDerived->myFunc();
Or (uglier & vehemently discouraged) static_cast the pointer up to derived class type and then call the function
NOTE: To be used with caution. Only use when you are SURE of the type of the pointer you are casting, i.e. you are sure that pbase is a derived or a type derived from derived. In this particular case its ok, but im guessing this is only an example of the actual code.
base* pbase = new derived();
static_cast<derived*>(pbase)->myFunc();
myfunc needs to be accessible from the base class, so you would have to declare a public virtual myfunc in base. You could make it pure virtual if you intend for base to be an abstract base class, i.e one that cannot be instantiated and acts as an interface:
class base
{
public:
virtual void myfunc() = 0; // pure virtual method
};
If you ant to be able to instantiate base objects then you would have to provide an implementation for myfunc:
class base
{
public:
virtual void myfunc() {}; // virtual method with empty implementation
};
There is no other clean way to do this if you want to access the function from a pointer to a base class. The safetest option is to use a dynamic_cast
base* pbase = new derived;
....
derived* pderived = dynamic_cast<derived*>(pbase);
if (derived) {
// do something
} else {
// error
}
To use the base class pointer, you must change the base class definition to be:
class base
{
public:
virtual void myFunc() { }
};
I see no other way around it. Sorry.
You could add it as a member of base and make it a virtual or pure virtual function. If using this route however, you should also add a virtual destructor in the base class to allow successful destruction of inherited objects.
class base
{
public:
virtual ~base(){};
virtual void myFunc() = 0;
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};