Base-to-derived class typecast - c++

I have a base class:
class RedBlackTreeNode
{
// Interface is the same as the implementation
public:
RedBlackTreeNode* left;
RedBlackTreeNode* right;
RedBlackTreeNode* parent;
Color color;
TreeNodeData* data;
RedBlackTreeNode():
left(0),
right(0),
parent(0),
color(Black),
data(0)
{
}
// This method is to allow dynamic_cast
virtual void foo()
{
}
};
and a derived from it one:
class IndIntRBNode : public RedBlackTreeNode
{
public:
IndIntRBNode* left;
IndIntRBNode* right;
IndIntRBNode* parent;
IndexedInteger* data;
IndIntRBNode():
RedBlackTreeNode(),
left(0),
right(0),
parent(0),
color(Black),
data(0)
{
}
};
root() and rootHolder are defined in RedBlackTree class:
class RedBlackTree
{
public:
RedBlackTreeNode rootHolder;
RedBlackTreeNode* root()
{
return rootHolder.left;
}
...
}
Then I'm trying to typecast:
IndIntRBNode *x, *y, *z;
z = dynamic_cast<IndIntRBNode*>(root());
And "z" just becomes a zero-pointer, which means that typecast failed.
So what's wrong with it, how can I fix it to be able to reference "z" as pointer to the IndIntRBNode?
Added: the initialization of the rootHolder.left was some kind of that:
int n = atoi(line + i);
tree.clear();
int j = 0;
if (n > 100)
{
n = 100; // Maximum 100 nodes
}
while (j < n)
{
IndexedInteger num(j,j + 10);
RedBlackTreeNode* node;
int c = tree.search(&num, tree.root(), &node);
if (c != 0)
{ // if value is not in the tree
IndexedInteger* v = new IndexedInteger(num);
tree.insert(node, v, c);
++j;
}
}
In the other words, it was initialized on the first iteration of "while" by the "insert" method in such way:
void RedBlackTree::insert(
RedBlackTreeNode* parentNode,
TreeNodeData* v,
// If it's negative, then add as the left son, else as the right
int compare
)
{
assert(parentNode != 0 && compare != 0);
RedBlackTreeNode* x = new RedBlackTreeNode;
x->data = v;
x->parent = parentNode;
// If it's root
if (parentNode == &rootHolder)
{
// Then it must be black
x->color = Black;
}
else
{
// Leaf must be red
x->color = Red;
}
if (compare < 0)
{
// Insert the node as the left son
assert(parentNode->left == NULL);
parentNode->left = x;
}
else
{
// Insert the node as the right son
assert(parentNode != &rootHolder && parentNode->right == NULL);
parentNode->right = x;
}
++numNodes;
if (x != root())
{
rebalanceAfterInsert(x);
}
}
It actually was the problem: "insert" created the RedBlackTreeNode dinamically, so it couldn't be IndIntRBNode.
I really have initialized it wrong, but then how can I derive the base class and not write the whole implementation of it from a scratch just to change the types?
Do I really have to override all the "type-relative" methods in the derived class? It seems to be very stupid, I think there should be the other way - something with class deriving and typecasting, isn't it?

Are you sure that RedBlackTree::rootHolder.left has been initialized?
I think you somewhere initialized IndIntRBNode::left, but when you are accessing RedBlackTree::rootHolder.left you are accessing RedBlackTreeNode::left, which is not the same field.

Wait .. you have a derived class with a type of the same name as the base class. How does that even compile?
how is rootHolder.left initialised? Because if a dynamic_cast fails then it is not of type IndIntRBNode.
Basically you haven't provided enough code to see hy what you are doing is wrong, but you ARE doing something wrong.

If I'm reading your code correctly, you are not setting rootHolder.left to a IndIntRBNode pointer at all, but a vanilla RedBlackTreeNode.
Also, you don't need to make up a useless virtual function for polymorphism; just declare the destructor to be virtual and provide an empty implementation. Your use of polymorphism also isn't that great, as the IndIntRBNode members will hide the RedBlackTreeNode members, so they may well point to different things depending on whether you access them through an IndIntRBNode pointer/reference or a RedBlackTreeNode pointer/reference.

Regardless of whatever other flaws your example code may or may not have, it is written in a way that seems to misunderstand how inheritance and casting work. I recommend that you pick up a C++ book of your choosing and read up on it.
In particular, you should know that every object is one and only one type. Once an object has been created it never changes type. Casting a pointer does not convert an object from one type to another, nor does it create a new object of a new type. Casting allows you to work with an existing object in terms of the class type you specify, but only if that object is already of that class, or a class that is derived from it.
At the point where you currently have this line:
z = dynamic_cast<IndIntRBNode*>(root());
try this instead:
RedBlackTreeNode* other_z = root();
If other_z is not NULL, then root() is not an IndIntRBNode, and all the dynamic_casting in the world won't turn it into one.

Related

Inheritance and pointers

I have code like this:
class Human
{
protected:
int age;
std::string sex;
public:
virtual void speak() = 0;
};
class Child:public Human
{
public:
void speak(){std::cout << "I am Child\n";}
};
class Man:public Human
{
public:
void speak(){std::cout << "I am Man\n";}
};
class Woman:public Human
{
public:
void speak(){std::cout << "I am Woman\n";}
};
(don't know, std::shared_ptr<Human> maybe?) operator*(std::shared_ptr<Child> &b, int x)
{
b->setAge(b->getAge()+x);
if(b->getAge()>18 && b->getSex()=="Man")
{
return (i want b to become std::shared_ptr<Man>)
}
if(b->getAge()>18 && b->getSex()=="Woman")
{
return (here I want b to become std::shared_ptr<Woman>);
}
return;
}
int main(){
auto x = std::make_shared<Child>;
x*19;
}
I know it seems odd, but it's the simplest case i can think of, without having to write down all code i'm struggling with rn. Could someone explain, what type should overload be and how to change shared_ptr type, knowing they derive from same parent?
Objects cannot change type. A Child object will always be a Child object. What you can do is create a new object with the properties you want and return that:
std::shared_ptr<Human> operator*(std::shared_ptr<Human> b, int x)
{
b->setAge(b->getAge()+x);
if(b->getAge()>18 && b->getSex()=="Man") {
return std::make_shared<Man>(b->getAge());
} else if(b->getAge()>18 && b->getSex()=="Woman") {
return std::make_shared<Woman>(b->getAge());
} else {
return b;
}
}
int main(){
std::shared_ptr<Human> x = std::make_shared<Child>;
x = x*19;
}
This doesn't seem like a good design though. A Human's status as a child or adult would be better represented as an attribute of the object or by a function that checks if age is greater than 18.
You cannot make the type T<Derived> inherit from T<Base> because C++ templates do not support covariance. To do so would be unsafe for certain types, such as mutable references to containers. (Imagine taking a reference to std::vector<Cat> as std::vector<Animal>& and pushing back a dog!)
(I would make this answer a comment, but I don't have comment abilities.)
Update:
You can write a non-template wrapper that handles heap data:
class Wrapper
{
public:
Wrapper(Base* b) : raw(b) {}
~Wrapper() { delete raw; }
Base& get() { return *base; }
private:
Base* raw;
}
Of course, in your example, you use std::shared_ptr and not std::unique_ptr. You would have to handle reference counting instead of simply deleting the data in the destructor, but the technique of keeping an internal raw pointer still stands.
Update 2:
The above code could be used as is to provide a level of indirection, such that all classes that inherit from the base class may be held in the same type, without writing your own reference counter:
std::shared_ptr<Wrapper>
This solution may be seen as similar to doing std::shared_ptr<Base*>, except that the latter solution would leak memory.

What is the C++ way to deal with class templates and their types?

I thought I have understood the concept of class templates in C++, but looking at my code I am not so sure anymore. Say I have two classes, a non-template parent and a template as child, like this:
class MyParent
{
std::string m_Name;
MyParent(std::string Name) : m_Name(Name) { }
virtual const std::type_info& GetType() = 0;
};
template <class T>
class MyChild : public MyParent
{
T m_Var;
const std::type_info& GetType() override
{ return typeid(m_Var); }
};
Now in my code I have a container with instances of MyChild using a different type, for example:
MyParent* p1 = new MyChild<int>("one");
MyParent* p2 = new MyChild<float>("two");
MyParent* p3 = new MyChild<double>("three");
std::vector<MyParent*> v = {p1, p2, p3};
So far this is clear, now to where my confusion starts. Say I have a function somewhere that iterates over this vector, then it needs to do some stuff with each element. Some example I just made up (my question is not about the code itself, but how to deal with such a situation):
/* ... */
for(auto* p : v)
{
if(p->GetType() == typeid(int))
{
int val = p->m_Var;
std::list<int> lst = {val, 1, 2, 3};
if(val >= 0)
SomeTemplFuncPositive(v * v, lst); // a template variadic function
else
SomeTemplFuncNegative(v * v * -1, lst);
}
else if(p->GetType() == typeid(float))
{
/* ... now the same block c&p again for float? */
}
else if(p->GetType() == typeid(double))
{
/* ... and again for double?! */
}
}
/* ... */
In other languages like Python for example I would have this code block only once, but in C++ it seems to me I would need to copy the whole code block again for float, and another time for double, and so on...
I don't want to blame C++, if that is the way it has to be, then ok. I am just wondering, is this really the correct approach in general when using such a construct in C++?
Your virtual-ity needs to be adjusted:
class MyParent
{
std::string m_Name;
MyParent(std::string Name) : m_Name(Name) { }
virtual void doSomething()=0;
};
template <class T>
class MyChild : public MyParent
{
T m_Var;
void doSomething() override
{
T val = this->m_Var;
std::list<T> lst = {val, 1, 2, 3};
if (val >= 0)
SomeTemplFuncPositive(v * v, lst);
else
SomeTemplFuncNegative(v * v * -1, lst);
}
};
Now, you invoke doSomething() through its base class:
for(auto* p : v)
{
p->doSomething();
}
Everything is written exactly once.
If you need to cast from Base to Child, your code is most likely wrong (at least in C++). While you're storing pointers to derivatives you should be sure that you won't need public access to their specific members (yet virtual methods still can do so). In this case, list should be declared in derivative and take T as template parameter.
Also, you don't need GetType function, you can use dynamic_cast<DerivativeClass*>(baseClassPtr), it returns proper pointer if casting is ok, and nullptr if casting can't be done.

Passing an array of Child objects to a function that accepts Parent*

I am working on an embedded platform with limited capabilities, so vectors/STL are not available.
This may be a trivial problem, but I do not have much experience in C++ (only C and C#, which may make me blind to an obvious c++ way to do it).
Consider the following example:
class Parent {
};
class Child : public Parent {
};
void Test(Parent* parents, uint8_t parentCount) {
// Accessing parent[x] is problematic when 'parents' contains a derived type
}
int main() {
// This is OK
Parent parents[3];
Test(parents, 3);
// This causes problems
Child children[3];
Test(children, 3);
return 0;
}
Obviously it is problematic to iterate over parents in Test(), if a pointer to an array of derived classes is provided, because the memory footprint of Parent is assumed during the iteration.
The only solution I see is to pass an array of pointers of type Parent (Parent** parents), but that seems cumbersome. Is there some C++ mechanism I am not aware of, like passing the array as a reference or something?
You could use this approach:
template <class T>
void Test(T* parents, uint8_t parentCount) {
// Code that accesses parent[x]
}
and then use it like this:
int main() {
Parent parents[3];
Test(parents, 3);
Child children[3];
Test(children, 3);
return 0;
}
If template is not an option and when the user of Test can not depend on Child and can't even know it's size, then you can use an array of pointers:
void Test(Parent** parents, uint8_t parentCount);
int main() {
Child children[n];
Child* pointers[n];
for(int i = 0; i < n; i++)
pointers[i] = &children[i];
Test(pointers);
}
Note that in this trivial example, we do know the size of the object whose pointers we pass, but in general, we may not be able to make that assumption for all users of Test.
If you can't use templates, you can do this:
class Parent {
};
class Child : public Parent {
};
void Test(Parent* parents, uint8_t parentCount, uint16_t parentSize) {
for (uint8_t ii = 0; ii < parentCount; ++ii) {
void* parentvoid = reinterpret_cast<char*>(parents) + ii * parentSize;
Parent* parent = parentvoid;
}
}
int main() {
Parent parents[3];
Test(parents, 3, sizeof(parents[0]));
Child children[3];
Test(children, 3, sizeof(children[0]));
}

C++: Cloning and overloading with multiple inheritance

This is a follow-up to this question. Someone asked about a minimal example, but I found it impossible to condense it all into something working. I still have issues, so I hope that by giving a bit more structure I can get some idea of what I am doing wrong or what I should be doing.
The classes I use form a tree structure, like this:
struct Base
{
/* nodeType is a number uniquely assigned to each concrete class */
int nodeType;
int numberOfA;
int numberOfB;
int NumberOfC;
int numberOfD;
AdvancedA** A_array;
AdvancedB** B_array;
AdvancedC** C_array;
Intermediate1** D_array;
virtual Base clone() = 0;
}
struct Intermediate1 : Base
{
}
struct Intermediate2 : Base
{
}
struct Advanced_A : Intermediate1
{
/* There might be different signatures since arguments might be
* real-valued, complex, or even matrices
*/
virtual double compute(signature 1);
virtual double compute(signature 2);
}
struct Advanced_B : Intermediate1
{
virtual std::complex compute(signature 1);
virtual std::complex compute(signature 2);
}
struct Advanced_C : Intermediate2
{
virtual matrix compute(signature 1);
//for example; definition of matrix class is not shown
}
struct Instance_A1 : Advanced_A
{
}
struct Instance_A2 : Advanced_A
{
}
...
struct Instance_B1 : Advanced_B
{
}
...
struct Instance_C1 : Advanced_C
{
}
...
I use these objects to build expression trees, which can evaluate to different types, corresponding to the three Advanced types. (Think of them as real-valued, complex-valued and matrix-valued expressions.) Because I need to evaluate the expressions, I have created three different types of expression trees, as follows.
struct BasicTree
{
virtual void cloneTree();
}
struct TreeType_A : BasicTree
{
Advanced_A* root;
}
struct TreeType_B : BasicTree
{
Advanced_B* root;
}
struct TreeType_C : BasicTree
{
Advanced_C* root;
}
I hope to eventually be able to use these in this manner:
TreeType_A* tree_A;
TreeType_B* tree_B;
TreeType_C* tree_C;
TreeType_A* copy_A;
TreeType_B* copy_B;
TreeType_C* copy_C;
copy_A = tree_A->cloneTree();
copy_B = tree_B->cloneTree();
copy_C = tree_C->cloneTree();
tree_A->root->compute(signature 1);
tree_B->root->compute(signature 1);
tree_C->root->compute(signature 2);
I have two concerns: The cloning of the array of Advanced elements will have to also clone the descendants. At the moment I put his into the method itself:
Base* Instance1::clone()
{
Base* temp = new Instance1();
(clone local stuff)
for (int i = 0; i < numberOfA; i++)
temp->A_array[i] = this->A_array[i]->clone();
for (int i = 0; i < numberOfB; i++)
temp->B_array[i] = this->B_array[i]->clone();
for (int i = 0; i < numberOfA; i++)
temp->C_array[i] = this->C_array[i]->clone();
for (int i = 0; i < numberOfD; i++)
temp->D_array[i] = this->D_array[i]->clone();
return temp;
}
If possible I would actually prefer to write a method cloneChildren that takes care of the recursion transparently.
Mostly I want to avoid having to use explicit casting. Different instances of the Advanced classes have different content, and this content seems to get lost if I try to write, e.g.
temp->A_array[i] = ((Advanced_A*)this->A_array[i])->clone();
On the other hand, using a long case statement based on the particular instance seems inefficient. So it seems I need to rely on automagic.
If further simplifications are possible, such as collapsing everything into a single tree type, or a single array of children, that would be great. (I doubt the former will work, because the compute functions need to look different and return different values for each type of root. The latter seems more promising to me.)
What other pitfalls might there be?

Pointer sets to null-pointer when going out of function

I have quite a blocking problem which I don't understand. Generally, I'm making a kind of anthill simulation. There is one main passage inside divided into segments and from some of the segments ants can enter into chambers. All of these three classes (Passage, Segment, Chamber) have one common thing - collection of ants currently visiting them. So there is an abstract class AntHolder, which contains vector<Ant*> (only members relevant to the case are shown):
class AntHolder
{
protected:
std::vector<Ant*> ants;
/* some other members here */
public:
virtual bool antEnter(Ant* ant) = 0;
/* some other functions here */
};
The antEnter function is implemented differently in derived classes, but generally serves the purpose of adding ant to the ants. From the derived classes particularly I'm interested in AntChamber class (here also less important members were omitted):
class AntChamber : public AntHolder
{
protected:
int itemCapacity;
int additionalCapacity;
std::vector<Item*> items;
bool hasFood;
bool hasEgg;
public:
bool putItem(Item* item);
virtual bool antEnter(Ant* ant);
};
The putItem function is similar to the antEnter function, but it adds Item objects to items collection. (Items are e.g. food, which are moved by ants from one chamber to another.) Below there is shown implementation of both functions:
bool AntChamber::antEnter(Ant* ant)
{
if (items.size() + ants.size() == itemCapacity + additionalCapacity) return false;
ants.push_back(ant);
return true;
}
bool AntChamber::putItem(Item* item)
{
if (items.size() == itemCapacity ||
items.size() + ants.size() == itemCapacity + additionalCapacity)
return false;
if (item->getItemKind() == Food) hasFood = true; // Food == enum value
else if (item->getItemKind() == Egg) hasEgg = true; // Egg == enum value
items.push_back(item);
return true;
}
You can clearly see, that they're almost identical. But when it comes to their effect, there is crucial, surprising difference, and that is the core of my problem.
Let's say I already have an AntChamber* chamber constructed. When I run the following piece of code:
Item* item = new Item(Food);
chamber->putItem(item);
, then after that both item and chamber->items.back() points to some memory with this object. But when I run the analogous piece of code:
Ant* ant = new Ant(chamber);
chamber->antEnter(ant));
, then after that ant point to the object, but chamber->ants.back() points to NULL!
I absolutely can't understand what is going on, especially, that both putItem and antEnter in fact do the same thing: push_back the pointer, which was passed by parameter. I have already tried to simulate such case in some simplier code, like:
class A { };
class B { };
class C
{
vector<A*> va;
vector<B*> vb;
public:
A* vaBack() { return va.back(); }
B* vbBack() { return vb.back(); }
void addA(A* a) { va.push_back(a); }
void addB(B* b) { vb.push_back(b); }
};
int main(int argc, char** argv)
{
A* a = new A();
B* b = new B();
C* c = new C();
cout << (unsigned int)a << endl;
c->addA(a);
cout << (unsigned int)c->vaBack() << endl;
cout << (unsigned int)b << endl;
c->addB(b);
cout << (unsigned int)c->vbBack() << endl;
delete c;
delete b;
delete a;
}
, but it appears to work just fine - none of pointers is 0x000000.
Oh My God, I'm sooo blind...
I did SSCCE, as Shafik Yaghmour advised and I noticed the problem while doing it.
I used a mental leap, saying, that chamber->items.back() or chamber->ants.back() are NULL, because in fact, they weren't! But they're protected in their classes, so I wrote in both classes a function to get to i-th item/ant. The problem was this function. It made a standard idiotproof protection against giving index out of vector's bonds, but made a mistake doing so:
if (idx < 0 || ants.size() >= idx) return 0; // SHOULD BE <= !!!
return ants[idx];
so it always returned 0... And I looked at this method maybe hundreds of times when looking for this problem, and never noticed anything wrong (till now).
Stupid mistake... Thank you very much Shafik.