C++ Have two child classes share a variable from their base class - c++

So say I have 3 classes: Base, A, and B.
Base is a base class for both class A and class B.
Base has a variable val that A and B can access.
How would I get it to work where I can set the val variable through class A, and it is reflected in class B?
For example:
I know this code below won't work because I am creating an OBJECT of the type a and b.
What I want to do is to simply have a and b share the same variable so that whenever a does something to it, it is reflected in b.
a aa;
b bb;
aa.SetVal(50000);
cout << aa.GetVal() << endl;
cout << bb.GetVal() << endl;
In the end I'd want both cout lines to print out 50000.
EDIT: The classes A and B will be doing different operations and just need to be able to access/change the val variable in base

You could make the member a static member of the base class, then all derived classes could access it, however any object of a derived that changes the static member would change it for every other object.
class Base
{
public:
int GetVal()
{
return val;
}
void SetVal( int newVal )
{
val = newVal;
}
private:
static int val;
};
// Need to instantiate the static variable somewhere
int Base::val = 0;
class A : public Base
{};
class B : public Base
{};

class Base {
static int value;
public:
virtual ~Base() { }
void setVal(const int& val) {
value = val;
}
int getVal() const {
return value;
}
};
int Base::value = 0;
class A : public Base {
};
class B : public Base {
};
#include <iostream>
int main() {
A a;
B b;
a.setVal(20);
std::cout << b.getVal(); // 20
}

That's a job for references, not for classes. Just have one class X and create a reference to the object:
X aa;
X& bb = aa;
aa.SetVal(50000);
std::cout << aa.GetVal() << std::endl;
std::cout << bb.GetVal() << std::endl;
The output will be:
50000
50000
Remember to always use the right tool for the job and keep things simple.
The main goal is that those two classes will be doing different things but will need to be able to access and share a single variable.
An idea to solve this is to extract the common variable in another class, namely S, which will be passed to A and B like this:
std::shared_ptr<S> s = new S();
A aa(s);
B bb(s)
Now, both aa and bb share the same S object and can modify it very easily. Notice that the constructor of both A and B should store the std::shared_ptr<S> as well:
class A { // and B
private:
std::shared_ptr<S> s;
public:
A(std::shared_ptr<S> as) : s(as) {}
};
The variable s will last as long as any of aa and bb is alive: when both aa and bb gets deallocated or go out of scope, the variable s will be deallocated as well.
If the type of the common variable should be on the stack, you can also just use references, but watch out for the lifetime of aa, bb and that variable:
int s = 0;
A aa(s);
B bb(s);
with:
class A { // and B
private:
int& s; // or any other type
public:
A(int& as) : s(as) {}
};
But as a general rule of thumb I'd avoid shared state between objects. Most of the time, depending on the context, you can refactor your code and get rid of the shared dependency.

If the shared value is static in the base class, then all instances of derived classes will see exactly that one base class member.
If the value is not static, then each instance of a class will have its own copy whether or not the value is in a base class.

Not sure I understand what you are trying to do. Do you want all instances of A and B to share the same value? if so, declare it as static in the base class.
if not, how do you want to choose which one will share the value?

Related

Using a pointer to an object as a member of another object

For certain reasons, I want to have multiple instances of class A all have access to a single instance of class B. B has public member functions that allow objects of A to get data from B, but not to change it. I'm trying to do this by declaring an object of B in my main function, then passing it to the constructor when I declare objects of type A.
void main () {
B obj_b;
A A1(obj_b);
A A2(obj_b);
A A3(obj_b);
cout << A1.getfoo() << endl;
cout << A2.getfoo() << endl;
count << A3.getfoo() << endl;
}
class B{
private:
int foo = 9;
public:
int getfoo(){return foo;}
};
class A {
private:
B *bptr;
public:
A(B b){ this->bptr = &b; }
int getfoo(){ return bptr->getfoo(); }
};
This compiles and runs, but I get very weird results. The return values from getfoo are sometimes correct sometimes incorrect. Am I handling the pointers incorrectly? Is there a better way to do this?
In the A constructor, the argument b is a local variable, its life-time ends when the constructor function ends. You can't save a pointer to it, that pointer will become invalid immediately.
Either use smart pointers, or use a reference and constructor initializer lists:
class A
{
public:
// Pass by reference
A(B& b)
: b{ b } // Initialize the member variable b with the argument b
{
// Empty body
}
private:
B& b; // Reference to a B object
};

Upcast to abstract base class

I try to have an abstract base class act like an interface and instantiate a derived class based on user input. I tried to implement it like this
class A
{
public:
virtual void print() = 0;
};
class B : A
{
public:
void print() override { cout << "foo"; }
};
class C : A
{
public:
void print() override { cout << "bar"; }
};
int main()
{
bool q = getUserInput();
A a = q ? B() : C();
a.print();
}
But that does not work. I’m coming from c# and that would be valid c# so I’m looking for an equivalent way of implement it in c++. Could someone please give me a hint? Thanks!
There are two problems with the code in its current state.
By default in C++, a class that inherits from a class or struct will be private inheritance. E.g. when you say class B : A, it's the same as writing class B : private A -- which in C++ restricts the visibility of this relationship only to B and A.
This is important because it means that you simply cannot upcast to an A from outside the context of these classes.
You are trying to upcast an object rather than a pointer or reference to an object. This fundamentally cannot work with abstract classes and will yield a compile-error even if the code was well formed.
If the base class weren't abstract, then this would succeed -- but would perform object slicing which prevents the virtual dispatch that you would expect (e.g. it won't behave polymorphically, and any data from the derived class is not present in the base class).
To fix this, you need to change the inheritance to explicitly be public, and you should be using either pointers or references for the dynamic dispatch. For example:
class A
{
public:
virtual void print() = 0;
};
class B : public A
// ^~~~~~
{
public:
void print() override { cout << "foo"; }
};
class C : public A
// ^~~~~~
{
public:
void print() override { cout << "bar"; }
};
To model something closer to the likes of C#, you will want to construct a new object. With the change above to public, it should be possible to use std::unique_ptr (for unique ownership) or std::shared_ptr (for shared ownership).
After this, you can simply do:
int main() {
auto a = std::unique_ptr<A>{nullptr};
auto q = getUserInput();
if (q) { // Note: ternary doesn't work here
a = std::make_unique<B>();
} else {
a = std::make_unique<C>();
}
}
However, note that when owning pointers from an abstract base class, you will always want to have a virtual destructor -- otherwise you may incur a memory leak:
class A {
public:
...
virtual ~A() = default;
};
You can also do something similar with references if you don't want to use heap memory -- at which point the semantics will change a little bit.
References in C++ can only refer to an object that already has a lifetime (e.g. has been constructed), and can't refer to a temporary. This means that you'd have to have instances of B and C to choose from, such as:
int main() {
auto b = B{};
auto c = C{};
bool q = getUserInput();
A& a = q ? b : c;
a.print(); // A& references either 'b' or 'c'
}
You need to use pointers :
A* a = q ? static_cast<A*>(new B) : new C;
...
delete a;
A ternary is also a special case here, as it takes the type of the first expression.
If C inherited from B here it would not be a problem.

using derived class data members from base class method

So i have been trying to use derived class data members from the base class and i am not able to figure out how to do that. I see a way to do this as just passing the member i need in parameter when i call the base class method but i was just thinking that there should be another way to do that. So i have replicated this as below.
#include<iostream>
using namespace std;
class B;
class A{
public:
display(){
cout<<cord<<endl;
}
int cord = 25;
};
class B : public A{
public:
B(){
A a;
a.display();
}
int cord = 30;
};
class C : public A{
public:
C(){
A a;
a.display();
}
int cord = 35;
};
int main(){
B b;
C c;
B.display();
}
The above code as giving output as
25
25
25
What i want it to give out is
30
35
30
Every way to do this will be appreciated, whatever is better and if you want to me add something or anything ask in comments, i'll do right away.
define a virtual getter like
virtual int getCord() const { return cord; }
in each class and call it in display
void display(){ cout << getCord() <<endl; }
and in the constructor of B and C you also need to replace
A a;
a.display();
just by
display();
else there is no chance you access to the value of the sub classes explicitly calling display on an instance of A
using derived class data members from base class method
This is because of that I let the redefinition of cord in B and C, but I do not recommend you to do that kind of redefinition in 'real' codes ;-)
Lets take the B constructor:
B(){
A a;
a.display();
}
In it you create a completely separate object a of type A, and call display on it. That display call will be using the a object, not knowing anything about the B class or its totally separate cord member variable at all.
One possible way to solve this is to create a constructor of A that takes the value of cord as an argument, pass the "correct" value in the B constructor initializer list, and then call the display function on this object:
struct A{
A() = default;
explicit A(int c)
: cord(c)
{
}
display(){
cout<<cord<<endl;
}
int cord = 25;
};
struct B : A{
B()
: A(30)
{
display(); // Equivalent to this->display();
}
};
Of course, you need to do something similar for the C class (or structure).
Note that I removed the member variable cord from the B class. That's because if you declare a new member variable with the same name as a member variable in a base class, then you effectively create a completely new member variable that is unrelated to the one in the parent class. And for the simple example you show there's no need to "override" the member variable, as it already exists in all child-classes as well.

OOPS Memory Allocation for Base class under Inheritance?

Program:
class A
{
int a;
public:
void geta()
{
a=10;
}
void puta()
{
cout<<"a : "<<a;
}
};
class B : public A
{
int b;
public:
void getb()
{
geta(); b=20;
}
void putb()
{
puta(); cout<<"b : "<<b;
}
};
int main()
{
B ABC;
ABC.getb();
ABC.putb();
return 0;
}
The Problem:
The above program allocates memory for derived class object & calls its relevant methods.
The base class is inherited as public, and as the variable 'a' is a private member, it will not get inherited.
So, the program should not allocate memory for this variable.
But, when the above is executed, 'a' variable will be allocated even though it is not inherited.
Could anyone help me understand this?
Thank You.
as the variable 'a' is a private member, it will not get inherited. So, the program should not allocate memory for this variable.
Your assumption is mistaken. Public inheritance models an "is-a" relationship. That is, class Derived is-a Base. Anything you can do with a Base, you should be able to do with a Derived. In order for this to be true, it necessarily must contain everything that Base contains.
In your example, it's perfectly legal to say:
B b;
b.put_a();
that is, to use A methods on B object. This would not work if the a member was absent.
The base class is inherited as public, and as the variable 'a' is a private member, it will not get inherited.
When a base class member is declared as private it doesn't mean it does not get inherited. It just means that the member variable will be inherited (will be part of the derived class) but won't be accessible.
For example, in:
class A {
private:
int a;
int b;
// ...
};
class B : public A {};
auto main() -> int {
B b;
}
When we allocate B b; we are allocating both a and b member objects of the class A.
The variable a is inherited, though you have no access to it. For example, the following code would work:
class A {
private:
int x;
public:
int getXfromA() { return x; }
};
class B : public A {
public:
int getXfromB() { return getXfromA(); }
};
However, x cannot be directly accessed from B class here.
You're confusing storage with access control.
If object B inherits from object A, it has all of object A's methods and members, even if it cannot access them directly.
The purpose of private and protected is access control. If you mark members and methods as private, then nothing outside can access those methods and members. But, those things are part of the object nonetheless.
This allows you to implement class invariants without exposing the details, including classes that inherit from the base.
Here's an example that encapsulates capturing the creation time of an object in the base class:
#include <time.h>
#include <iostream>
class Base
{
private:
time_t create_time;
public:
Base()
{
create_time = time(0);
}
time_t get_create_time() { return create_time; }
};
class Derived : public Base
{
public:
Derived() { }
};
int main()
{
Derived D;
std::cout << D.get_create_time() << std::endl;
}
Derived doesn't know or need to know how the creation time was captured. It's a class invariant it inherited by deriving from Base.
This is a pretty simple example, but you could imagine more complex examples.

Learning inheritance

I am trying to understand inheritance and I need some help building two classes. The fist one is called A, the second one is called B.
A has one private integer value "m_a". It has two constructors, the default one sets m_a to 5. and another one which takes as an argument an integer called m and sets m_a's value to m. As for member functions it will have two. The first one will return m_a. The second one will print "Hello from A!". Let's move on to B. B will have a private string m_s. A default constructor which will set m_s to "asd" or to anything other than an empty string and a constructor which will take as an argument a string and set m_s to it's value. As far as functions go, firstly B will have a function that will return m_s. It will have a function which will have the same name as the print "Hello from A" function in A which will override it and it will printout "Hello from B!" instead (is that polymorphism ?).
Those are the classes needed. I have the following questions (I will post what I have created below)
Firstly, is there any way I can get to the private data fileds from the base class. For example let's say I want to take the m_s variable, add it to another one and print out their sum. Is that possible ? (and how)
Also when I try to create a class with a constructor different from the default one I get errors. I am obviously doing something wrong. The question is what.
I think those are all of my questions for now, so it is time for me to post the source code.
#include <iostream>
#include <string>
using namespace std;
class A
{
private:
int m_a;
public:
A(){m_a = 5;}
A(int m)
{
m_a = m;
}
void pm()
{
cout << "Hello from A!" << endl;
}
int get_a()
{
return m_a;
}
};
class B : A
{
private :
string m_s;
public:
B(){m_s = "asd";}
B(string s)
{
m_s = s;
}
void pm()
{
cout << "Hello from B!" << endl;
}
string get_s()
{
return m_s;
}
};
int main()
{
A a(10);
a.pm();
cout << a.get_a() << endl;
B b("asd");
b.pm();
cout << b.get_s() << endl;
cout << b.get_a() << endl;
return 0;
}
(is that polymorphism ?).
Not the way you have done it. It would be polymorphism if you had a pointer of type A* which pointed to what was actually a B object, and calling pm on that pointer correctly invoked the member function of B. This would only be possible if the pm function in A were declared as virtual, like below.
class A
{
...
virtual void pm(){
...
};
...
int main()
{
A* = new B();
A->pm(); //"Hello from B!"
}
is there any way I can get to the private data fileds from the base class
Not sure what you mean here - your example talks of a private field of the derived class.
Typically good class design means that derived class should not need to access the (private) fields of the base class, if this is needed you should make that field protected.
As to the compile error #ArunKumar got it exactly.
When you say Class B : A You inherit from A, but all the members are inherited as private by default, due to this, base class constructor is private, so you cannot use it.
However when you say Class B : public A it is the other end of the spectrum. All members of the base class retain their accesibility in the derived class (public remains public, etc)
The problem is that you're using private inheritance:
class B : A {
Inheritance through classes are private by default. Add public before A.
class B : public A {
As for your other problem...
I want to take the m_s variable, add it to another one and print out their sum.
This is easy when it comes to std::string. Just create another member function:
void addTom_s(string s) { m_s += s; }
Trying changing class B : A to class B : public A