#include<cstdio>
#include<iostream>
using namespace std;
class A
{
public:
int x;
};
class B: public A
{
};
int main()
{
B b;
b.x=5;
cout<<b.x<<endl;
return 0;
}
i have the above code.it's all okay.but i want to know when i inherit class B from class A does the member variable x declared in class B too just like A or the class B just get access to the member variable x of class A ?
are there two variables with the same name in two different classes or there are only one variable and the objects of the both classes have access to it ?
if there are two different variables with the same name in two different classes then why, when an object of derived class is declared the constructor of base class is called ?
When you create an object of the derived class, a base class sub-object is embedded in the memory layout of the derived class object. So, to your question, there's only on variable that will be a part of the derived object.
Since, we are only taking about non-static members here, each derived object gets its base-class sub-object laid out in memory.
When you create a base class object, its a different piece of memory representing different object and has nothing to do with derived object created earlier.
Hope it clarifies your doubt!
This is a great book to understand C++ object model:
http://www.amazon.com/Inside-Object-Model-Stanley-Lippman/dp/0201834545/ref=sr_1_1?ie=UTF8&qid=1412535828&sr=8-1&keywords=inside+c%2B%2B+object+model
Related
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.
I have a question regarding what "this" points in derived classes in C++.
class A
{
int a;
public:
void funca() { cout << this << endl; }
};
class B
{
int b;
public:
void funcb() { cout << this << endl; }
};
class Derived : public A, public B {};
int main() {
Derived d;
d.funca();
d.funcb(); // prints 4bytes more than the above.
}
In this case, how are "this" in base classes interpreted in the derived class?
Is it this of the derived class or this of the base class??
From the output, I think this points to the class object where it is used. Am I right?
how are "this" in base classes interpreted in the derived class?
I guess the question should be How base classes resides in derived classes
When a class is inherited by another, the compiler kind of places the members of base class in the derived class. The this always refers to the actual object, you are right about this. d.funcb(); prints 2 bytes ahead because, members of B starts after 4 bytes of A in Derived. This 4 bytes is taken by A::a member variable. But the layout and memory model is not guaranteed, and varies depending on compiler. One possible memory layout for Derived may be
Members of A (4 byte in this case for a)
Members of B (4 byte in this case for b)
Members of Derived (if any)
So derived class does not have a Base class "this", there is only one this, which refer to the actual object. And derived classes get copy of base class members in them.
Class Derived contains two subobjects A and B. These subobjects have non-static member functions. The first implicit argument of these functions is the poinetr that points to the corresponding object.
So in your example when function funca is called it gets the pointer that points to subobject A inside class Derived. The same way when function funcb is called it gets the pointer that points to subobject B inside class Derived.
Shotly speaking in each class definition this denotes an object of the defined class. In the class definition of class A this denotes an object of class A. In the class definition of class B this denotes an object of class B. Inside class Derived subobjects A and B have different locations i.e. different addresses. So the output in your example will differ.
I guess the topic is all I need to ask. A little explanation around the topic would be nice. Please clear some questions like why or why not?
Example:
class A {
private:
int a;
};
class B : A {
int b;
};
int main (int argc, char **argv) {
B *p = new B(); // Does this allocate memory for a?
}
Yes. A class object contains all of its direct non-static data members, and those of any base-class sub-objects. Access specifiers make no difference; they merely restrict where names can be used.
It depends on what you mean with allocate: it does not do a heap allocation or something. A derived object will contain the members inherited from the base. That is all base classes of a derived class can be seen as subobjects. The derived class objects will contain all these subobjects and will also make sure that they are properly constructed/destructed.
Yes it will allocate memory for A also.
Because when you inherit a class from another class and when you create the object of derived class, Complier will allocate memory equal to size of derived class+base class,so that there would be no loss of data.
As base class members are also accessible from derived class.
I was wondering if someone could explain to me how I might be able to implement something similar to this:
namespace advanced_cpp_oop
{
class A
{
B b;
};
class B : public A
{
};
}
int main()
{
}
Where an instance of a base class can contain an instance of a derived class? When the above code is compiled the following error is generated:
g++ advanced_cpp_oop.cpp
advanced_cpp_oop.cpp:8:5: error: ‘B’ does not name a type
The (almost) equivalent Java code which does compile is:
public class AdvancedCppOop
{
public static void main(String[] args)
{
A a;
}
}
class A
{
B b;
}
class B extends A
{
}
Thanks
You need to add a pointer and a forward declaration:
namespace advanced_cpp_oop
{
class B;
class A
{
B* b;
};
class B : public A
{
};
}
In your C++ code, you are creating an instance of your class B inside class A, which is not possible since the compiler does not yet know anything (especially not the size) of class B.
With the code from my answer, you need to dynamically allocate an instance of class B and assign it to the b pointer somewhere else in your code.
On a side note, from design perspective, this does not really make sense since a parent class should not depend on a sub class.
You have to do it with some type of pointer, such as unique_ptr, and a forward declaration:
class B;
class A
{
std::unique_ptr<B> b;
};
class B : public A
{
};
This is silly though and you should probably rethink your design.
There is one very important difference between C++ and Java. C++ is a language with value semantics, while Java is a language with reference semantics. When in Java you create a variable of anything other than a primitive type, you are not creating an object of that type, but a reference to such an object. On the contrary, in C++ the same construct refers to an actual object.
If you keep this in mind, it is simple to understand why the following cannot possibly work:
class Base {
Derived d;
};
class Derived : Base {};
The first definition in C++ means that the object Base contains internally (not by reference) an object of type Derived. At the same time, Derived contains by means of inheritance a subobject of type Base.
That means that Derived contains a Base that contains a Derived containing a Base...
What would be the size of Base or Derived?
In a language with reference semantics, or in C++ if you use pointers, that is not a problem. The Base object contains a reference/pointer to Derived. Derived contains a Base subobject by means of inheritance. The size of Base is well known: all the other fields plus the size of a reference/pointer. The size of Derived is whatever the size of Base is plus any extra members that are added.
Andreas beat me to the correct answer, but I'll just add that the Java code works only because Java objects are implicitly held by pointers (hence the B b = new B(...); statements sprinkled throughout Java code) even if it doesn't look like it. Your original C++ code doesn't work (even with a forward declaration of class B added) because the compiler doesn't know how big a B object is, and thus doesn't know how big an A object that contains it will be. On the other hand, all pointers have the same size (regardless of pointed-to type), so the compiler has no such problems when you replace a B object with a pointer to a B object in class A.
I'm assuming that my base class has one "int" member and the derived class has also one "int" member. Now when I create one derived class object and see the output by sizeof(derivedClassObject) then it is becoming 8. Now I am troubling to grasp the underlying idea here.
I know that when I create an object for the derived class then both the base class constructor and derived class constructor are get called. The only purpose of base class constructor here is to initialize the base class data members. I expected that the sizeof will display 4 because I am only interested to create a derived class object. But instead of that I am getting output as "8". So, extra 4 byte is being allocated and I think its happening for the base class constructor. I would appreciate if anyone help me to grasp the following concepts:
Why 8 bytes are being allocated instead of 4 when I create a derived class object? Does it mean that base class constructor is also creating a new base class object and concatenating it with the new derived class object?
I am just creating one derived class object and the size of that derived class object is: sizeof(baseClassObject) + sizeof(derivedClassObject). I would really appreciate to get some help.
In general inheritance in oop means that an object of a derived class is also an object of the base class. Therefore it contains everything the base class contained (in this case one int, so 4 byte) and any additional data members from the derived class (so another int).
If that wasn't the case, how would an object of the derived class be usable as an object of the base class? Inherited methods would likely do horrible things, since the data members they are trying to access wouldn't exist.
Therefore the sizeof(derivedClass)==sizeof(baseClass) + sizeof(int) (although nothing is keeping the compiler from making it bigger).
If you don't want your derivedClass to be usable as a baseClass you shouldn't derive from it.
Assume you have two classes as below
class Car {
int make;
public:
Car(int m): make(m) {}
int getMake() { return make; }
};
class Audi : public Car{
int internalID;
public:
Audi(int m, int id): Car(m), internalID(id){}
int getInternalID() { return internalID; }
};
Now I go ahead and create an object of Audi
Audi *myCar = new Audi(2012 /*make*/, 216487 /*internal ID*/);
you can do something like
myCar->getInternalID(); //returns 216487
myCar->getMake(); //returns 2012
If your assumption that creating the derived class should allocate space only for derived members, where would 'make' be stored in this case?
A derived class is nothing but baseclass + members declared in derived class. Hence your derived object would look something like this in memory
------------
| make |
------------
| internalID|
-------------
Hence you get the size of derived class members plus size of base class. Again, size of base class will be size of base class members plus size of its base class. Hope this helps!