Why doesnt the subclasses share the same private membervariable in the superclass using polymoprhism? There are only one instance of the baseclass and if SubA is setting the private member through a mutator - why then cannot SubB access this value. How would it look like if I want the subclasses to share the same private member?
#include <iostream>
class Super {
private:
int cnt;
public:
int getCnt() {
return cnt;
}
void setCnt(int cnt) {
this->cnt = cnt;
}
};
class SubA: public Super {
};
class SubB: public Super {
};
int main() {
Super *super;
SubA a;
SubB b;
super = &a;
super->setCnt(10);
super = &b;
std::cout << super->getCnt() << std::endl;
super = &a;
std::cout << super->getCnt() << std::endl;
return 0;
}
produces:
-8589546555 (garbage)
10
There are only one instance of the baseclass and if SubA
That is wrong. a and b are different objects. They each have an instance of an A sub object. You have not set cnt in b, so it is no surprise that looking at it gives you a garbage value, because reading from an uninitialized object is undefined behaviour.
How would it look like if I want the subclasses to share the same private member?
You could give the base class a static data member. That means all instances of A would share the same member.
Why doesnt the subclasses share the same private membervariable in the superclass using polymoprhism?
Polymorphism has nothing to do with how data is embedded in classes; (run-time) polymorphism is only relevant to virtual dispatch and Run-Time Type Information (RTTI) for dynamic_cast and type_info.
If you imagine your a and b objects on the stack, their memory layout can be illustrated like this:
A:[[Super: int cnt;]A-specific fields (if there were any)]
B:[[Super: int cnt;]B-specific fields (if there were any)]
In effect, class A : public Super is saying "I may want to extend 'Super', optionally appending my own data members to those in Super, possibly adding further functions / overriding virtual ones".
There are only one instance of the baseclass and if SubA is setting the private member through a mutator - why then cannot SubB access this value.
This is wrong... each sub class embeds its own instance of the super class.
How would it look like if I want the subclasses to share the same private member?
Well, there are lots of ways in which you could orchestrate that:
You could have the subclasses hold pointers to a Data object into which you move the superclass's data you want shared, then you'd need a way to initialise the Data object and make it known to all the subclass instances you want to share it.
You could make the superclass data static, which means a single copy of each static variable will be shared by all instances of the superclass, whether embedded in subclasses or not.
Related
I have this large class that I want to separate into different classes. The reason why it was large because the class had many private variables and functions that are needed to run the program. I was tired of scrolling down the 1000+ lines of code trying to add or edit code. I am wondering if it is possible for the classes to interact with one base class that includes all the private/protected variables it needed to operate, or simply have them as global variables.
I am aware of inheritance as I tried having the separate classes be derived from the base class, by doing something similar to this:
#include <iostream>
class Base {
public:
void sayPrivateVar() {
std::cout << privateVar;
}
protected:
std::string privateVar = "I am a protected variable!";
};
class Derived : public Base {
public:
void manip() {
base->privateVar = "That was updated from a derived class";
}
private:
Base* base;
};
int main() {
Base base;
Derived derived;
derived.manip();
base.sayPrivateVar();
return 0;
}
EDIT: Without creating another object inside a class.
it depends on your class and what you have in it. It is often better not have inheritance because derived classes may then get member variables that they don't need. There are a few other ways you can do. One way would be to group you private variables in different classes and then have member variables in the first class.
E.g.
class X {
int x;
int y;
int angle;
...
};
becomes
class XYVector;
class X {
XYVector v;
};
class XYVector
{
int x;
int y;
int angle;
};
You can continue in this direction and instead of making them concrete class like XYVector above have them as interfaces : to have it more elaborate and flexible check out https://en.wikipedia.org/wiki/Composition_over_inheritance
At any rate: avoid having globally declared variables.
This is a good question and the answer is absolutely. Inheritance is actually a very good solution in this particular context since that is how object code shares it's scope with other classes. One important thing to note here is that how you call your derived class is important because the inherited scope is set along with the derived class (i.e. declaring it public base would inherit the public and protected methods as opposed to declaring it private which would give the derived class even more access!)
I have an abstract class base with private member variable base_var. I want to create a derived class, which also has base_var as a private member.
To me, this seems like an obvious thing you would want to do. base is abstract so it will never be instantiated. The only time I will create a base-object is if it is actually a derived object, so obviously when I give ´base´ a private member variable, what I am really trying to do is give that variable to all of its derived objects.
However, the below diagram seems to suggest that this is not doable with inheritance?
Why not? What would then even be the point of having private stuff in an abstract class? That class will never be instantiated, so all that private stuff is essentially useless?
However, the below diagram seems to suggest that this is not doable with inheritance?
Correct, private members of a class can not be accessed by derived classes. If You want a member of a class to be accessible by its derived classes but not by the outside, then You have to make it protected.
Why not? What would then even be the point of having private stuff in an abstract class? That class will never be instantiated, so all that private stuff is essentially useless?
Even an abstract class can have member functions which act on a (private) member variable. Consider (somewhat silly example, but well):
class MaxCached
{
private:
int cache = std::numeric_limits<int>::min();
public:
bool put(int value)
{
if (value > cache)
{
cache = value;
return true;
}
return false;
}
int get() const
{
return cache;
}
virtual void someInterface() const = 0;
};
Deriving from this class gives You the functionality of the base class (put and get) without the danger of breaking it (by for example writing a wrong value to cache).
Side note: Above is a purely made up example! You shouldn't add such a cache (which is independent of Your interface) into the abstract base class. As it stands the example breaks with the "Single Responsibility Principle"!
Just because a class is abstract doesn't mean there cannot be code implemented in that class that might access that variable. When you declare an item in a class to be private, the compiler assumes you had a good reason and will not change the access just because it there is a pure virtual function in the class.
If you want your derived classes to have access to a base class member declare the member as protected.
I have an abstract class base with private member variable base_var
class foo {
public:
virtual void a_pure_virtual_method() = 0;
int get_var() { base_var; }
virtual ~foo(){}
private:
int base_var;
};
Note that a class is said to be abstract when it has at least one pure virtual (aka abstract) method. There is nothing that forbids an abstract class to have non-pure virtual or even non-virtual methods.
I want to create a derived class, which also has base_var as a private member.
class derived : public foo {};
To me, this seems like an obvious thing you would want to do.
Sure, no problem so far.
The only time I will create a base-object is if it is actually a derived object, so obviously when I give ´base´ a private member variable, what I am really trying to do is give that variable to all of its derived objects.
Still fine.
Why not?
You are confusing access rights that are display in the image you included with the mere presence of the members in the derived. The derived class has no access to members that are private in the base class. Period. This is just according to the definition of what is private.
What would then even be the point of having private stuff in an abstract class? That class will never be instantiated, so all that private stuff is essentially useless?
It is not useless at all. Derived classes inherit all members, they just cannot access all of them. The private stuff is there you just cannot access it directly. Thats the whole point of encapsulation. Consider this example:
class bar : public foo {
void test() {
std::cout << base_var; // error base_var is private in foo
std::cout << get_var(); // fine
}
};
Assume the following:
class A {
public:
A();
protected:
int a;
};
class B : public A {
public:
B();
};
My questions:
Can I access (directly) the protected data members of A and maybe modify them without having to use public member functions?
Can I treat A inside B as an "existing" object so that I can return A by reference and be able to modify its data member?
I am new to C++. I tried couple things to treat "A" as an object but I keep getting error messages. Here is one thing I have tried:
A & B::getA() {
return A; //error: "A does not refer to a value"
}
Can I access (directly) the protected data members of A and maybe
modify them without having to use public member functions?
A protected member variable or function is very similar to a private member but it provided one additional benefit that they can be accessed in child classes which are called derived classes.
Can I treat A inside B as an "existing" object so that I can return A
by reference and be able to modify its data member?
In B you can directly access to A (public and protected) method and attributes.
Read here for more.
To return a reference to your base class you can write
A & B::getA() {
return *this;
}
to access A's protected data member you can simply write
a = 5;
Whenever I derive a new class from base class say:
#include <iostream>
class A {
protected:
int f;
public:
void get() {
std::cout << "The address is: "
<< &f << std::endl;
}
};
class B : public A {
// ....
};
int main() {
A a;
a.get();
B b;
b.get();
return 0;
}
The address is: 0xbfb0d5b8
The address is: 0xbfb0d5bc
Does this means that all the code from class A will be copied to class B? Since I have nothing in class B i.e. no data members or functions So, when I create an instance of class B, then I find that it has its own variable at different address and it also has a member function. How can it have its own of copy members if it they aren't copied?
Is that what do we mean by code reuse in inheritance?
Edit:
Updated my code to reflect what I meant by copying of variables.
Code is never copied during inheritance. But when the child object (class B) is created or instantiated at run time, it inherits the functionality and attributes of the parent class/object (class A).
the code from class A does NOT copied to class B in the sense that there is only one place the code is written.
however, and here cones the Reusable part, when using class b u can call the method and use the members, with respect to private, public, etd and thus does not have to write the same code for two class that do the same thing
for example if i have a circle and a square, and they both have a member called color that i want a method that change it, i do not need to write the method and the member twice, but have them inherit class Shape that will implement it once and then they both will be able to use that method, thus reusing one method in two places
I'm not sure "copied" is the right word (the compiler will only compile the code in class A once). As you have used public inheritance, class B actually is a special type of class A. As such, class B does have access to every (non-private) member of class A, so the code is re-used.
In addition, from the conversation in the comments:
No. Nothing is "copied", each instance of A and B has their own value for their own variables, except for any static data members. For static data members, again there is no copying going on; there is simply only one variable and that is shared by all instantiations of A and B.
In your example, you are comparing two different instances of two different classes. different instances means different base addresses to store instances data.
Perhaps a better test of whether a field of a class is copied over in derived classes is the following:
#include <iostream>
class A {
protected:
int f;
public:
void get() {
std::cout << "The address is: " << &f << std::endl;
}
};
class B : public A {
// ....
};
int main() {
B b;
b.get();
A *a = &b;
a->get();
return 0;
}
And the output is:
The address is: 0x7fff41d523f0
The address is: 0x7fff41d523f0
With that program, we can see that even though we have an instance of class B, its inherited content is physically the same as the one in the original class A. Note that it is also possible to redefine a class member in a derived class, but the original member will still be available if we coerce an instance of the derived class to the parent class (as I did in my example).
§1.8(2) of the C++ language standard defines what is meant by a subobject:
Objects can contain other objects, called subobjects. A subobject can be a member subobject (9.2), a base class subobject (Clause 10), or an array element. An object that is not a subobject of any other object is called a complete object.
These are examples of member subobjects and array elements, which you should be familiar with:
int a[5];
a[2]; // the third array element subobject of the complete object a
struct S { int x; }
S s;
s.x; // a member subobject of the complete object s
That leaves the remaining kind of subobject, the one which you are interested in: base class subobjects.
struct B { int x; }
struct D : public B { int y; }
D d;
d.y; // a member subobject of the complete object d
d.x; // a member subobject of a base class subobject of the complete object d
B &b = d; // a reference to a base class subobject of the complete object d
Every instance of a derived class contains an instance of its base class, as a base class subobject.
I also have some doubts regarding relation between inheritance and code re-use. This is my take on this.
Inheritance is a mechanism used to categorize and facilitate polymorphism. Using inheritance we can build a hierarchy of concepts separated in categories at different levels of abstraction. By doing this, we can efficiently use another OOP concept, polymorphism, which allows the same control code to manage all objects in a category even if they are different in their implementation.
I don't think that we use inheritance for code re-use purpose.
Below code is not compiling for me...
class Base
{
public:
Base(){}
virtual void Display()
{
cout << "Base Display" << endl;
}
};
class Derived : private Base
{
private:
void Display() override
{
cout << "Derived Display" << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Derived d;
d.Display();
Derived* dp = new Derived();
dp->Display();
delete dp;
return 0;
}
Compiler reporting errors when I am calling Derived::Display(). How to call it?
What kind of problems we can solve by writing code like this?
You can't access a private method from outside the class. Hence the compilation error.
You are mixing two different concepts here, the access specifier of the member function and the access specifier of the base class.
You cannot call the member function because its access specifier is private and you are attempting to call from a function that is not a friend. That is regardless of the type of inheritance from Base or even if that relationship exists.
The access specifier in the inheritance relationship determines what parts of the code can consider your type to be a Base and which cannot. In this particular case, inside Derived and its friends you can use a reference or pointer to Derived as if it was a Base, but not outside of it.
How to call it? What kind of problems we can solve by writing code like this?
Private inheritance models implemented in terms of, and can be used to provide some functionality through the use of a third party library/class hierarchy from which your own type need not conceptually derive. Avoiding the public inheritance inhibits your users from seeing you as the base, which is intentional as that is a detail of implementation. Inside your own type, you can use the inheritance relationship:
void detail(Base *base) {
base->Display(); // Base::Display is public
}
void Derived::show() { // Derived::show is public:
detail(this); // Private inheritance is visible inside Derived
}
You've made Display private in the derived class, so it's accessible via a pointer/reference to Base, but not directly in a Derived object, nor via a reference/pointer to Derived.
// This should work:
Base *b = new Derived;
b->Display();
// and so should this:
Derived d;
Base &b = d;
b.Display();
...but either of these would also require public inheritance to allow implicit conversion from Derived to Base.
You can't call a derived class method with private inheritance out side of class it become private even if it's defined as public.
Private inheritance hides every method and attribute from outer world, thus your Derived instances on heap or stack cannot call Display directly like you did in your main function. You can replace private with public to avoid these kind of errors or use a pointer to Base to access hidden base methods.
Edit: Improved with suggestion by Jerry.
Private inheritance creates a "contains-a" relationship (it is effectively like creating a member variable of the type Base). What you are attempting to do is create an "is-a" relationship, which is done through public inheritance.