The reason why baseclass pointer cannot be assigned to derived class pointer - c++

Can any explain why baseclass pointer cannot be assigned to derived class pointer? I know it is not possible ,but i like to know the reason .logically derived class contain base class.Let me know the reason
Thanks in advance

Consider:
struct A
{
};
struct B : A
{
int b;
};
struct c : A
{
char c;
};
C cobj;
A* aptr = &cobj;
B* bptr = aptr; // Assuming this were allowed...
bptr->b = 10;
By doing that you'd have used memory beyond what is valid. You have created an object of size sizeof(C) but not you are treating it like it is of size sizeof(B).

A derived class can have its own data members and member functions in addition to all of those within the base class.
If you point the derived class pointer to the same thing as a base class pointer, the derived class pointer will think it's pointing to a derived class object, even though it's pointing to a base class object.
If you try to access derived class data members or member functions using this derived class pointer, it won't work because it's pointing to a base class object that doesn't have these capabilities.
For instance, let's assume I have a base class called Person and a derived class called Programmer. I can make a Person object and have a pointer point to that object. I can then try to make a Programmer pointer point to that Person object as well (by setting it equal to the Person pointer). If I used my Programmer pointer to try and make the Person object code (equivalent to calling a Programmer member function) or do something only a Programmer does, it wouldn't work because the Person hasn't been specialized.

I assume your question is why following should not be done:-
Derived *ptr = new Base; //assume for now public inheritance.
Derived is specialization of Base i.e Derived would inherit all features of base plus it could also add some of its own features. That means assigning Base to Derived ptr leads to loss of those features which could result into undefined behavior if call is made to that variable/method.

Related

Multiple inheritance and "this" pointer being cast to common base class

Consider the following code:
class Base {
//some code
};
class A : public virtual Base{
//some code
};
class B : public virtual Base{
//some code
};
class C: public A, public B {
//some code
};
In other words we have multiple inheritance and all classes inherit from class Base. Now consider that the "this" pointer exists in code in classes A,B,C,Base. I know that in general we cannot assume that the "this" pointer value will be identical in all cases. But what it the "this" pointer is cast to the Base* class inside A,B,C whenever it is used. Is it correct to say that the casted pointer "this" after casting to the common Base* class will contain the same address inside A,B,C? Thanks
Yes. The virtual inheritance means that there is only one base class subobject of type Base, which is simultaneously a subobject of the C and the A and the B. A conversion (implicit or by cast) from pointer to any of those types to Base*, or initializing a reference Base& from lvalue of any of those types will cause the compiler to do the correct logic to find that single Base subobject.
But what it the "this" pointer is cast to the Base* class inside A,B,C whenever it is used
Note that there isn't even a need to cast (i.e. convert explicitly). A pointer to derived converts to base pointer implicitly.
Is it correct to say that the casted pointer "this" after casting to the common Base* class will contain the same value inside A,B,C?
A pointer doesn't "contain values" other than the value of the address of an object. The object whose address is stored is the pointed object. A pointer to a base points to the base sub object.

Use existing base class object when allocating a derived class

I need help with a specific programming problem in C++ (not sure if this is even possible in C++). I need to be able to access all public member functions in Base class, but do not want to allocate memory for the Base class data while allocating the Derived class object.
Lets say, I have:
class Base
{
public:
Base();
~Base();
int GetFoo() { return foo; }
// other public member functions of Base class
private:
int foo;
// other data
};
class Derived : public Base
{
public:
Derived(Base *BasePtr);
Derived(Base &BaseRef);
~Derived();
double GetXyz() { return xyz; }
// other public member functions of Derived class
private:
double xyz;
// other data
};
Now, lets say I already have a Base class allocated and initialized. I want to create a new Derived class object by referring to that existing Base object and allocate memory only for the data specific to the Derived class. Following the above example, I would have already allocated memory for "int foo" in the Base class object and only want to allocate memory for "double xyz" in the Derived class object.
Base *basePtr = new Base();
Derived *derivedPtr = new Derived(basePtr); // what is the content of this function?
What should be the memory allocation or the constructor for the Derived class look-like? I want to inherit all data and member functions of the Base class, but without doing a "combined" data allocation of Base and Derived. I have tried overloading operator new but no luck. Any help is appreciated.
I'm not sure if it fits your requirements, but you could simply copy the contents of the Base stored in basePtr inside a new Derived object, then delete the Base object and point at the new Derived object with the old Base pointer. Like this:
Base *basePtr = new Base();
/* Do something with base here */
Derived *derivedPtr = new Derived(basePtr);
delete basePtr;
basePtr = derivedPtr;
derivedPtr = 0;
That way you'll end up with only one object (of type Derived) and won't have to store a separate pointer to it, nor store the Base object, and that seems like what you need.
Update:
in my case, I cannot delete the Base object since I would have created millions of them (using GigaBytes of RAM space) and people could be using pointers/references to those objects, so copying them to Derived objects and deleting the old Base objects doesn't work for me.
In that case, maybe you should try to do an "extendable* structural wrapper. First create an simple class without any method or member:
class Additional{};
Then create a wrapper structure:
struct wrapper{
Base *basePtr;
Additional *moreInfo;
}
Then, instead of deriving your Derived class from Base, derive it from Additional. And instead of storing milions of Base pointers, store milions of wrapper pointers. IT'll make your code a bit longer and harder to understand, but it'll do what you need. Well - unless the only thing your Derived class adds is a pointer or any data that takes less size.
If you've got virtual functions in Base, in order to use them with the new hierarchy, oyu'll just have to check every time:
wrapper *wrapperPtr = &alreadyCreatedSomewhereWrapper;
if(wrapperPtr->moreInfo)
wrapperPtr->moreInfo->function();
else
wrapperPtr->basePtr->function();
Use multiple inheritance.
class Base()
class Derive1() : Base
class Derive2() : Base
class MostDerive() : Derive1 , Derive2
MostDerived() will be thin. Derive1 and Derive2 will need to be deterministically constructed, but that can be imposed, or some Init() functions can be used.

Assigning class to base class, how do do it?

I'm confused about assigning the base object of a derived class. Say I have a type:
class Base {
// stuff omitted for brevity
}
and a derived class
Derived : public Base {
// stuff omitted
}
and I have a situation that arises like this:
Derived = Base;
Is this possible? What is this operation called? How would I do such a thing?
Thanks for your help.
This is a perfectly ordinary user-defined assignment that looks enough like "slicing", treating a base class as if it were a member, to confuse the unwary. But it's not slicing. For the situation you have, the two classes might as well not be related, and you define the assignment that way.
struct d : b {
d &operator=(const b &b_) { /*do the work here*/; return *this; }
};
You might be able to use the base class's copy-assignment operator, or you might not:
struct dx : b {
dx &operator=(const b &b_)
{
this->b::operator=(b_);
// more work
return *this;
}
};
but the compiler gives this no special treatment, it's the same as any function call.
You should almost never assign a base class object to a derived class object, because then a derived object is only partly assigned which may not be consistent. But there are times that you may need to cast a pointer of a base class object to a pointer of a derived class object
Base *pb = new Derived;
..
Derived *pd = dynamic_cast<Derived*>(pb);
This is used when you want to identify the exact type of the object pointed by a base pointer(but actually pointing to the drived object, like in this example). Usually you should avoid this because it's time-consuming, and it's not a good design.
This is called object slicing and it is usually a bad thing. A Derived class is a Base class with more stuff. So when you assign a Derived object to a Base object, what should happen to the extra stuff? The operation doesn't make logical sense.

C++ Inheritance. Changing Object data Types

I am having trouble with forcing data type changes has on my own objects. I have a base class say A and two classes derived from A called B and C. I pass objects B and C to a function that checks which type of object it is (B or C). Here is some example code below and the question to my problem:
enum ClassType {"B", "C"};
class A {
protected:
m_Type;
public:
ClassType Type() { return m_Type}
...
...
};
class B : public A {
otherMemberFunctions();
}
class C : public A {
otherMemberFunctions();
}
void WhatType(vector<A*>* candidates){
vector<B*> b_candidates(0);
vector<C*> c_candidates(0);
for(int i = 0; i < candidates->size(); i++){
if(candidates->at(i)->Type() == B ){
B* b = (B*) candidates->at(i);
b_candidates(b);
}
//Same idea for Object C
}
}
I would then use WhatType(vector<A*>* candidates) as follows
vector<B*>* b_example
WhatType((vector<A*>*) b_exmaple)
When I have filled the new vector b_candidates in the function WhatType. Will I still have access to the member functions in the B object or will I only have the access to the member functions in the base class A?
I am confused to what happens with the object when I change the type of the object.
Here
WhatType((vector<A*>*) b_exmaple)
and here
B* b = (B*) candidates->at(i);
When you receive a pointer to a polymorphic object you have two types: the "static" type of the object, which, in your case, will be A *, and its "dynamic" or "real" type, that depends on what was actually assigned to it.
Casting your A * to B * forces the compiler to consider that pointer as a pointer to B; this is safe as long as you actually know that that pointer is actually a pointer to B, otherwise the compiler will start writing nonsensical code (invoking B methods on data of another type).
The checks you are trying to implement are a homegrown version of RTTI, which is a mechanism that allows you to know which is the "real type" of a pointer or a reference to a polymorphic class, and to perform that kind of casts safely. Check out typeid and dynamic_cast on your C++ manual for more info about it. (Incidentally, IIRC dynamic_cast is not only for safety in case the dynamic type is wrong, but it may perform also some extra magic on your pointer if you use it in complicated class hierarchies; so, avoid C-style casting for polymorphic classes)
By the way, in general it's considered "code smell" to have to manually check the "real type" of the pointer in order to cast it and use its methods: the OOP ideal would be being able to do the work only though virtual methods available in the base class.
Big warning: RTTI works only on polymorphic classes, i.e. classes that have at least one virtual method. On the other hand, if you are building a class hierarchy where objects are being passed around as pointers to the base class you'll almost surely want to have a virtual destructor, so that's no big deal.
Since you cast to B*, you will have access to B's members.
The actual type of the objects does not change, of course, but if you only have a pointer (or reference) to the base class you can not access fields specific to the sub-classes.
What you can do to access sub-class fields is to use dynamic_cast to cast it to the sub-class:
A *a = new B; // We cant reach the members of class B in a
B *b = dynamic_cast<B *>(a); // But now we have a proper pointer to B
Ok, so if you had an object of type B instantiated on the heap and held by a pointer of type A. you can only see type A's member functions, to access type B's member functions you have to static_cast<B*> which is what the ... "(B*)" ... is doing.
dynamic cast is better as it will return a null if the conversion is not possible. but of course it happens a run-time so there's a penalty.
As B and C are À derived, a vector<B *> and vector<C *> contains A base class objects. If you ensure to set your A::m_Type attribute in your constructor, you will no have problems:
enum ClassType {'B', 'C'}; // see I modified your definition
class A {
protected:
ClassType m_Type;
public:
ClassType Type() { return m_Type};
...
...
};
class B : public A {
public:
B() : m_Type('B') {}
....
};
Using this, you will check without problems your B and Cobjects. After that, as you are casting base objects to derived ones, you will have fully access to their public methods and attributes.

A Base Class pointer can point to a derived class object. Why is the vice-versa not true?

A Base Class pointer can point to a derived class object. Why is the vice-versa not true without casting?
Logically a base class would not have enough information of the derived class but a derived class should have the information of the base class as well.
I am missing some basics here.
If I tell you I have a dog, you can safely assume that I have a pet.
If I tell you I have a pet, you don't know if that animal is a dog, it could be a cat or maybe even a giraffe. Without knowing some extra information you can't safely assume I have a dog.
similarly a derived object is a base class object (as it's a sub class), so it can be pointed to by a base class pointer. However, a base class object is not a derived class object so it can't be assigned to a derived class pointer.
(The creaking you will now hear is the analogy stretching)
Suppose you now want to buy me a gift for my pet.
In the first scenario you know it is a dog, you can buy me a leash, everyone is happy.
In the second scenario I haven't told you what my pet is so if you are going to buy me a gift anyway you need to know information I haven't told you (or just guess), you buy me a leash, if it turns out I really did have a dog everyone is happy.
However if I actually had a cat then we now know you made a bad assumption (cast) and have an unhappy cat on a leash (runtime error).
We have two objects.
class A {
int a;
};
class B : A {
int b;
};
Allocate an instance of B. We can interface with that as either an A* or a B*.
Allocate an instance of A. If we were to cast it to a B*, should there be space allocated for the member b?
Uh, because the base class is not a derived class.
When you have a valid pointer to a type, then you are saying that the object pointed to will have certain data in certain locations so that we can find it. If you have a pointer to a derived object, then you are guaranteeing that the pointed-to object contains all of Derived's data members- but when you point to a Base, then it infact doesn't have that and Bad Things Happen™.
However, Derived is guaranteed to have all of the Base data members in the same locations. That's why a pointer to Base can actually point to Derived.
Because a derived class includes everything that is in the base class. But a base class does not include everything that is in the derived class.
Type casting a base class to a derived class is not recommended: What happens if you try to access members that are not part of the base class?
This is valid, because a tiger is an animal:
Animal * pAnimal = new Tiger();
This is not valid, because it is not true that the object is a poison dart frog.
PoisonDartFrog * pPoisonDartFrog = new GenericFrog();
The short answer
class A{
public:
method1();
};
class B: public A{
public:
method2();
};
int main(){
// Case 1
A* ptr_base = new B();
// Here I can call all the methods in A by ptr_base even though it is assigned B ...
// ... because B is derived from A and has all the information about methods of A
// Case 2
B* ptr_derived = new A(); // this will cause error
// Now here ptr_derived is assigned information of A ...
// ... So with this information can I call (*ptr_derived).method2(); ?...
// ... the answer is No because A does not have information of method2() ...;
// ... thus this declaration loses its meaning and hence error.
return 0;
}
Because C++ is a statically typed language, and allowing implicit Base-to-Derived conversions would break the type system. Bjarne Stroustrup did not want any "message not understood" runtime errors.
class Base
{
public:
int a;
}
class Derived : public Base
{
public:
float b;
}
Base * pBase = new Base();
pBase->a = 7; // setting the value of a in the base
// make a pDerived that points to the SAME DATA as pBase
Derived * pDerived = pBase;
pDerived->a = 5; // this would be okay, base has a public member 'a'
pDerived->b = 0.2f; // error pBase has no data member b and pDerived
// points to the SAME DATA as pBase
This is because, "the type of a pointer is the type of object the pointer points to". So,
If we have base type pointer (*B):
then we expect a base type object (and would like to access its functionalities) at the address pointed by B, and if we get a derived type object at that address then also we are able to access the required functionalities. This is because derived type is-a base type.
If we have derived type pointer (*D):
then we expect a derived type object at the address pointed by D and if we get base type object there then we will not be able to access derived class info from the base type object since base type is-not-a derived type.
Actions speak more than words.
Child too can have Parent Class object.
if you understand pointers well, limitations are off to you
In below code have printed both values by child class pointer ( which was having Parent class object).
Also proved that by printing their address.
Any suggestions are welcome!
#include<iostream>
using namespace std;
class Baap{
public:
int a;
void hoo(){ cout<<"hoo\n"; cout<<a;}
};
class Beta:public Baap{
public:
int a;
int b;
void hee(){ cout<<"hee\n"; }
};
int main(){
Baap baap;
baap.a=1;
Beta *beta=(Beta*)&baap;
baap.a=3;
beta->hee();
beta->hoo();
cout<<"\n beta = "<<beta<<"\n&baap = "<<&baap;
return 0;
}
//output
hee
hoo
3
beta = 0x7ffd11dd3834
&baap = 0x7ffd11dd3834
Because a base class pointer can point to an instance of the base class or any derived type. A derived pointer can only point to that derived type or any subclass of it.
struct Base {};
struct Derived : Base {};
struct Derived2 : Base {};
Base* p = new Derived(); //Fine, Derived inherits from Base
Derived* d = new Base(); //Not fine, Base is not an instance of nor derived from Derived.
Derived* d2 = new Derived2(); // Also not fine, Derived2 derives from Base, but is not related to Derived.
As far as the why goes: In general the base pointer is more general than the derived pointer. As such it knows less about the inherited type. A derived pointer cannot be assigned a pointer to a base type without casting simply because it cannot tell if the base pointer is of the Derived type or one of its children.
If assign an address from a base class pointer into a derived class pointer, you can potentially assign a base class object to a derived class pointer. You run the risk of accessing derived class members when you don't have a derived class. Whereas derived class methods would work on a base class, they would only do so if the method didn't access derived class member data.
That's a huge risk.
So we force you to cast so that you have to acknowledge the disclaimer that says (you may make a stupid mistake, please be careful).
In general , a pointer of one type cannot point to an object of a different type. However, there is an important exception to this rule that relates only to derived classes.
In this situation a pointer of type BASE* may point to an object of type Derived, i.e a base class pointer can point to a derived class object but vice versa is not true as the base object is not it's sub class object.