Reaching inherited variables with base class pointers - c++

I learnt the work of virtual functions: if the inherited classes inherit a function from the base class, and it is custom for each ones, I can call these functions with pointers that point to the base class, this way:
BaseClass* PointerName = &InheritedClassObject;
But what about variables? I found this question on the site that tells: I can't create virtual variables in C++. My experience proves it: for variables, Visual C++ says: 'virtual' is not allowed.
Then, what is the way to reach the value of a(n inherited) variable that belongs to an inherited class by using base class pointers?

Based off your comment, I think what you are trying to ask if how do child classes access their parent's variables. Consider this example:
class Parent
{
public:
Parent(): x(0) {}
virtual ~Parent() {}
protected:
int x;
};
class Child: public Parent
{
public:
Child(): Parent(), num(0) {}
private:
int num;
};
void Child::foo()
{
num = x; //Gets Parent's x,
}
NB: If you define an x in Child, that masks the x in Parent. So, if you want to get the x in Parent, you would need: Parent::x. To simply get x from a Child c, you use c.x if x is public or use a getter if x is protected or private:
int Child::getNum()
{
return num;
}

You don't. Virtual functions use them, do whatever needs to be done and return result if needed.

You can't use any function, data member of an inherited class if it's casted back to base class. However, you can alter those variables with virtual functions. Example:
#include <iostream>
class BaseClass {
public:
BaseClass() {}
virtual void do_smth() = 0;
private:
};
class InheritedClass: public BaseClass {
public:
InheritedClass(): a(1) {}
virtual void do_smth() { std::cout << ++a << std::endl; }
private:
int a;
};
int main() {
BaseClass* ptr = new InheritedClass();
ptr->do_smth();
return 0;
}
In this piece of code, virtual function did alteration of variable belongs to InheritedClass.

Related

DerivedA pointer pointing to DerivedB

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;
}

Like, virtual function can we make a variable virtual in c++

when a base class pointer points to the object of it's derived class and if a function being overridden we use virtual function to solve the problem . So that we can access the own function of derived class using the pointer.
Like this , i was thinking that if there a way which can be applied on virtual keyword in variable , so that we can access the latest version of a variable in derived class using pointer.
#include <iostream>
using namespace std;
class base
{
public:
int x;//but what about this , if we add virtual keyword here.
//it will give error if trying to do so .
//but can you tell me what can i do if i want to make use of it as virtual function
//if not please tell me why
virtual void display(void) //to call the recent version of display function we make use of virtual here
{
cout << "base\n";
}
};
class derived : public base
{
public:
int x;
void display(void)
{
cout << "derived\n";
}
};
int main(void)
{
base *p;
base ob1;
derived ob2;
p=&ob2;
p->x=100;//here i want to set 100 to the x of derived class not that x which has been inherited
//But it sets to the x of base class which i dont wanted
p->display();//here we can access the latest version of display function in derived class
return 0;
}
Please, No body ask me why i want to do so.I don't have any intention to do in my real code. i asked for the curiosity.
No, you cannot use virtual for fields, only for methods.
However you can simulate that by creating a function that returns a reference to a field:
class Base
{
private:
int x;
public:
virtual int& X() { return x; }
};
class Derived : public Base
{
private:
int x;
public:
virtual int& X() override { return x; }
};
int main()
{
Derived d;
Base* b = &d;
b->X() = 100; // will set d's x
}
You can't override member variables with the virtual keyword. You could, however, have virtual getters and setters that refer to different member variables in the base and derived classes to achieve a similar effect:
class base {
public:
virtual int getX() {
return x;
}
virtual void setX(int x) {
this->x = x;
}
private:
int x;
}
class derived : public base {
public:
int getX() {
return x;
}
void setX(int x) {
this->x = x;
}
private:
int x;
}
The other answers are totally fine but you can also use the much simpler syntax:
class base {
public:
virtual operator int&() { return x; };
virtual operator int() { return x; };
protected:
int x;
};
if you have a single variable that you'd wish to virtualize in your class.
The second declaration is only to avoid using a reference when you just need the value, while when assigning the reference is automatically chosen for you.
You can override these operators at will from classes derived from base.
class derived : public base {
public:
operator int() override { return x * 5; };
}

Call overload function based on child in parent container

I'd like to store a child object in a container of its parent type, and then call a function overload based on the type of child in the container. Is that possible?
#include <vector>
class Parent { public: };
class A : public Parent { public: };
class B : public Parent { public: };
class C : public Parent { public: };
class Hander
{
public:
static void handle(A & a) {}
static void handle(B & b) {}
static void handle(C & c) {}
};
int main()
{
A test1;
Hander::handle(test1); // compiles and calls the correct overload
Parent test2 = A();
Hander::handle(test2); // doesn't compile
Parent * test3 = new A();
Hander::handle(*test3); // doesn't compile
Parent children1[] = { A(), B(), C() };
for (int i = 0; i < 3; ++i)
Hander::handle(children1[i]); // doesn't compile
std::vector<Parent*> children2 = { new A(), new B(), new C() };
for (int i = 0; i < 3; ++i)
Hander::handle(*children2[i]); // doesn't compile
}
No, it is not possible.
The function which is called is chosen at compile-time. Lets say you have code like this:
Base &o = getSomeObject();
handle(o);
The compiler doesn't know the real type of o. It only knows that it is some subtype of Base or Base itself. This mean it will search for a function which acceppts objects of type Base.
You could implement a check for the type yourself or use a map to store possible functions:
Base &o = getSomeObject();
functionMap[typeid(o)](o);
But typeid does only work this whay if Base is a polymorphic type. This mean it must have at least one virtual function. This brings us to the next section:
But you could use virtual functions.
Virtual functions are non-static member functions of classes which can be overridden. The right function is resolved at runtime. The following code would output Subt instead of Base:
class Base {
public: virtual std::string f() {return "Base"}
};
class Subt : public Base {
public: virtual std::string f() {return "Subt"}
};
int main() {
Subt s;
Base &b = s;
std::cout << b.f() << std::endl;
}
You can omit virtual in the definition of Subt. The function f() is already defined as virtual in it's base class.
Classes with at least one virtual function (also called polymorphic types) are storing a reference to a virtual function table (also called vtable). This table is used to get the right function at runtime.
The problem in your question could be solved like this:
class Parent {
public:
virtual void handle() = 0;
};
class A : public Parent {
public:
void handle() override { /* do something for instances of A */ }
};
class B : public Parent {
public:
void handle() override { /* do something for instances of B */ }
};
class C : public Parent {
public:
void handle() override { /* do something for instances of C */ }
};
int main()
{
std::vector<std::unique_ptr<Parent>> children = {
std::make_unique<A>(),
std::make_unique<B>(),
std::make_unique<C>()};
for (const auto &child : children)
child->handle();
}
Note about compatibility: The keywords auto and override are only available in C++11 and above. The range-based for loop and std::unique_ptr is also available since C++11. The function std::make_unique is available since C++14. But virtual function can be used with older versions, too.
Another hint:
Polymorphism does only work with references and pointers. The following would call Base::f() and not Subt::f():
Subt s;
Base b = s;
std::cout << b.f() << std::endl;
In this example b will just contain a object of type Base instead of Subt. The object is just created at Base b = s;. It may copy some information from s but it isn't s anymore. It is a new object of type Base.

Base class functions that use derived class variables

In c++, Is there a standard way to create a function in a base class that can use the variables of derived classes?
class Foo{
private:
int x;
public:
Foo(){
x = 2;
}
void print(){
std::cout << x << std::endl;
}
};
class Derived : public Foo{
private:
int x;
public:
Derived(){
x = 4;
}
};
void main()
{
Derived a;
a.print();
}
This code prints the variable of the base class ( 2 ). Is there a way to make a function used by many derived classes to use the class's private variables without passing them as parameters?
Edit: My intentions are, to avoid writing the same code for each derived class.
For example, I want a get_var() in all, but this function should return the variable of that own class. I know I can make virtual and override, but I was looking for a way that I don't need to write again and again.
No, it is not possible for the base class to access anything in the derived class directly. The only way for a derived class to share anything with its base class is by overriding virtual member functions of the base class.
In your case, however, this is not necessary: the derived class can set variable x in the base class once you make it protected, and drop its own declaration as unnecessary:
class Foo{
protected: // Make x visible to derived classes
int x;
public:
Foo(){
x = 2;
}
void print(){
std::cout << x << std::endl;
}
};
class Derived : public Foo{
public:
Derived(){
x = 4;
}
};

Is this c++ inheritance structure possible?

I have not programmed in c++ in a long time and want some simple behavior that no amount of virtual keywords has yet to produce:
class Base {
public:
int both() { return a(); }
};
class Derived : public Base {
protected:
int a();
};
class Problem : public Derived {
};
Problem* p = new Problem();
p.both();
Which gives me a compile-time error. Is this sort of behavior possible with c++? Do I just need forward declaration? Virtual keywords on everything?
No. You will have to use a pure virtual a in base.
class Base {
virtual int a() = 0;
int both() {
return a();
}
};
You should declare the a() function as a pure virtual method in the Base class.
class Base {
int both() {
return a();
}
virtual int a()=0;
};
Then implement the a() method in the Derived class
class Derived : public Base {
int a(){/*some code here*/}
};
And finally, Problem class doesn't see the both() method, since its private in Base. Make it public.
class Base {
public:
int both() {
return a();
}
};
Your function both() is private by default. Try:
class Base {
public:
int both() {
// ...
(In the future, it would be helpful if you tell us what the actual error message was.)
You need a() to be declared in class Base, otherwise the compiler doesn't know what to do with it.
Also, both() is currently a private method (that's the default for classes), and should be made public in order to call it from main.
You have multiple problems in your code :
unless you declare them public or protected, elements of a class are private as a default.
you need a virtual keyword to define a virtual function that would be callable in a parent.
new returns a pointer to Problem.
Here's a complete working code based on your test :
class Base {
protected:
virtual int a()=0;
public:
int both() {
return a();
}
};
class Derived : public Base {
private :
int a()
{
printf("passing through a!");
return 0;
}
};
class Problem : public Derived {
};
int main(void)
{
Problem* p = new Problem();
p->both();
}
tested on CodePad.
As others point out, you need to declare a() as pure virtual method of Base and change access to public to make your snippet work.
Here is another approach possible in c++: instead of virtual functions, you can use static polymorphism via the Curiously recurring template pattern:
template <class D>
class Base : public D
{
public:
int both() { return D::a(); }
};
class Derived : public Base<Derived>
{
public:
int a();
};
I'm posting this approach since you're asking what is possible in c++. In practice, virtual methods are most often a better choice because of their flexibility.