How to get subclass member in c++ - c++

For example I have two class
class A:
class A
{
private:
int a;
}
subclass B:
class B: private A
{
private:
char b;
public:
char getB();
}
code:
int main()
{
A* item = new B();
char b = (B)item->getB();
}
Should I use cast or should I redesign program if I need to do something like that? I dont want to use polymorphism.

The problems
1) B privately inherits from A. So only a B can cast a B* to an A*.
2) The priorities of your expression are same as (B)(item->getB()); So this will not compile as item is an A and A has no member getB().
3) It's better to use static_cast or dynamic_cast instead of the old C style cast.
The solution
1) Use public inheritance if you want to cast between your derived class and base class outside of the classes themselves.
2) Then use parenthesis:
char b = ((B*)item)->getB();
3) Or prefer more precise form:
char b = static_cast<B*>(item)->getB();
4) But when you're doing an downcast like this, it's at your own risk. If the A* pointer points to something else than a B or a class derived from B, then it's undefined behaviour.
As you consider having a polymorphic use of your type, you'd better have a virtual destructor so that you can delete item with the appropriate destructor (here it would use A's destructor instead of B's).
As soon as you've at least one virtual function, you can use the safer dynamic_cast:
if(dynamic_cast<B*>(item)) { // would be nullptr if item doesn't point to a B object
char b = dynamic_cast<B*>(item)->getB();
... // further processing of the char
}
else cout << "Ooops!"<<endl;

You should use dynamic_cast that safely converts pointers and references to classes up, down, and sideways along the inheritance hierarchy (cppreference.com):
dynamic_cast<B*>(item)->getB();
, instead of old style C cast:
((B*)item)->getB();
Edit:
You should use public inheritance to use dynamic_cast. For what purpose private inheritance was used? In your example it doesn't make much sense IMHO. Also using inheritance without virtual destructor is dangerous.

Related

Does a static_cast of a derived object to base always select most derived object?

In the artificial example below, if I static_cast to the base class, when I call the setSnapshot() function it still calls the actual object setSnapshot(). This is what I want to happen. My question is can I always rely on this to work?
In code I am working on, we have this class hierarchy and in the b class there are macros used which static cast to the b type. This is to downcast from a base type so that specialised function in b can be called.
#include <iostream>
class a {
};
class b: public a {
public:
virtual void setSnapshot() { std::cout << "setting b snapshot\n"; }
};
class c : public b {
public:
virtual void setSnapshot() { std::cout << "setting c snapshot\n"; }
};
int main() {
a* o = new c;
//specifically casting to b
static_cast<b*>(o)->setSnapshot(); //prints setting c snapshot - what I want to happen
delete o;
return 0;
}
The title suggests that you're misunderstanding what the case does. new c creates an object of type c, and it will remain a c until it's destructed.
If you were to cast it to an a, you'd create a copy. But yu're only casting pointers. That doesn't affect the original object. That's still a c, and that's why you end up calling c::setSnapshot().
As long as a function is virtual in the statically known type a call of it will go to the override that is most derived.
For single inheritance this can be understood as a search for an implementation up the base class chain, starting in the most derived class.
In practice, for C++, the dynamic search is not done, and the effect of the search is instead implemented as a simple table lookup.

extending base class by casting it to derived and setting the data

Assume I have this:
class Base {
public:
int a;
Base() : a(5) {}
};
template<class T>
class Derived : public Base {
public:
T value;
};
The code below works but I want to know what can be the challenges of using such approach:
Base * base = new Base;
Derived<int> * derived = static_cast<Derived<int>*>(base);
derived->value = 5;
Derived<String> * derived1 = static_cast<Derived<String>*>(base);
derived1->value = "test";
Derived<String> * newderived = static_cast<Derived<String>*>(base);
std::cout << newderived->value;
Derived<int> * newderived1 = static_cast<Derived<int>*>(base);
std::cout << newderived1->value;
//Output: test1
Or how can I achieve such thing in a different, safer way. I want to pass a class through 5 functions that will manipulate it.
What you're doing here will fail horribly at some point because the size of the derived class is larger than the base class and you write after the end of the base class. The above write operation will overwrite memory that belongs to another object.
You can have a SetValue() method in the base class and implement it in the derived class.
The code does not work. All you objects even after casting are still a Base because you constructed them as a base. The casts just say: Hey, I know it's a Derived<xxx>, so please just interpret that this way. You don't know this here, in fact you know it is NOT a Derived.
To properly use the objects, you need to create a Derived<xxx> and afterwards cast. If you use a dynamic_cast here all cases should come back as null as they are Base.
Given that you wanted to "pass a class through 5 functions" you'd probably want the inverted setup. Create Derived<xxx> objects and hold them as a pointer to Base. This works without casting as it should. Then pass the Base* through your functions. Polymorphism will take care that everything works fine.

Is there a way to return a child* to a base* and evaluate which child* has been returned?

I tried this which didn't work:
void Map::OnLMClick(short xPos, short yPos)
{
SObject* pSObject = pEditWindow->GetSelectedItem();
if (pSObject==SOTile)
{
/* Do */
I tried this as a test:
SObject* EditorWindow::GetSelectedItem()
{
return pSOTile[1]; //pSOTile[1] is a valid pointer, member of EditorWindow
}
SOTile class is a child of base class SObject. So, is it possible to create a Base* to get one of its child's* returned and then have the program react differently depending of what child it returned? If it is the case, how do I then have access to members of it's child that are not members of base?
If your types are polymorphic (i.e. if they have at least one virtual function), you can use dynamic_cast:
Base* pObject = get_object(); // May return a pointer to Derived
Derived* pDerived = dynamic_cast<Derived*>(pObject);
Notice, that dynamic downcasts are sometimes an indicator of bad design. Try to think if a better arrangement of virtual functions in your hierarchy would help.
Without knowing the concrete application domain, it is not possible for me to give more concrete advices.
dynamic_cast operator performs a special checking when a class is polymorhic.
SOTile* pSOTile = dynamic_cast<SOTile*>(pSObject);
if (pSOTile)
{
/* Do */
}
Since SOTile is a pointer to a type that derives from SObject, you should not need to cast at all, since the compiler should be able to automatically resolve an SObject pointer from the derived pointer and then compare the two SObject pointers together (the same way that you can assign a derived pointer to a base pointer without type-casting). Some compilers, like Borland's, support that just fine, eg:
class Base
{
};
class Derived : public Base
{
};
Derived *d = ...;
Base *b = ...;
if (b == d) // <-- compiles fine
However, if for whatever reason your compiler does not allow that, you can manually cast the derived pointer using static_cast (don't use dynamic_cast to cast the base pointer):
if (pSObject == static_cast<SObject*>(SOTile))
If SOTile is not a pointer to a type that derives from SObject, static_cast will fail at compile-time.
I wouldn't recommend to use dynamic_cast. Instead, you can implement that different behavior in different child class. Sometimes called as "template method" pattern

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.

calling base class functions

I have following classes.
class A
{
public:
void fun();
}
class B: public A
{
}
class C: public A
{
}
A * ptr = new C;
Is it ok to do something like below? Will i have some problems if introduce some virtual functions in the baseclass?
((B *)ptr)->fun();
This may look stupid, but i have a function that calls A's function through B and i don't want to change that.
You can't cast an A* pointing to Class C as a B* because Class C doesn't have any relation with Class B. You'll get undefined behavior which will probably be the wrong function called and stack corruption.
If you intended for class C to derive from class B then you could. However, you wouldn't need to. If class C doesn't have fun() defined, it will inherit A's. You didn't declare fun() virtual though so you'll get strange behavior if you even implement C::fun() or B::fun(). You almost certainly want fun() to be declared virtual.
I'm guessing here but I suspect the behavior of this might depend on the compiler you use and how it decides to organize the vf pointer table.
I'm also going to note that I think what you are doing is a bad idea and could lead to all kinds of nightmarish problems (use of things like static_cast and dynamic_cast are generally a good idea). The other thing is because fun() is defined in the base class (and it is not virtual) ptr->fun() will always call A::fun() without having to cast it to B*.
You don't have to do the casting (B*) ptr->fun(); since the fun() is already in the base class. both objects of class B or C will invoke the same fun() function in your example.
I'm not sure what happens when u override the fun() function in class B...
But trying to invoke function from another class (not the base class) is bad OO, in my opinion.
You can cast from A * to B *, and it should work if the original pointer was B *.
A* p = new B;
B* q = static_cast<B*>(p); // Just work (tm)
But in this case it is a C *, and it is not guaranteed to work, you will end with a dangling pointer, if you are lucky you will get an access violation, if not you man end up silently corrupting your memory.
A* p = new C;
B* q = static_cast<B*>(p); // Owned (tm)