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

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]));
}

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.

Nested data structure where children inherit data from parent

I'm trying to create a nested data structure that is many layers deep where every "child" can access data from their parent/grandparent/etc...
for example take these data structures:
struct GrandChild {
int someGrandChildData;
};
struct Child {
int someChildData;
std::vector<GrandChild> vgrandChild;
};
struct Parent {
int someParentData;
std::vector<Child> vchild;
};
struct GrandParent {
int someGrandParentData;
std::vector<Parent> vparent;
};
The way I'd like to access the data would be like this:
void main()
{
// create and fill in the data
GrandParent gp;
for (int pNum = 0; pNum < 3; pNum++)
{
gp.vparent.push_back(Parent());
for (int cNum = 0; cNum < 3; cNum++)
{
gp.vparent[pNum].vchild.push_back(Child());
for (int gcNum = 0; gcNum < 3; gcNum++)
{
gp.vparent[pNum].vchild[cNum].vgrandChild.push_back(GrandChild());
// call function and ONLY pass a GrandChild
func(gp.vparent[pNum].vchild[cNum].vgrandChild[gcNum]);
}
}
}
}
void func(GrandChild &gc)
{
int result = gc.someGrandChildData;
// no need to pass GrandParent, Parent, or Child because
// GrandChild can access all of the data from them
result += gc.someChildData; // <<-- how can I achieve something like this
result += gc.someParentData; // <<-- how can I achieve something like this
result += gc.someGrandParentData; // <<-- how can I achieve something like this
}
I'm trying to do this because I have structures with many data members at each nesting layer and when I call functions it's extremely annoying to have to pass large numbers of arguments into each function call and becomes a mess to keep organized.
Any help would be greatly appreciated.
You could do it by keeping track of the Parent of every person(let's call it Node). So, for every Node, create an object of its direct Parent inside of it and do that for every layer (GrandChild, Child, Parent.. etc).
So each GrandChild will have a Child object, each Child will have a Parent object and each Parent will have a GrandParent object.
Then you will be able to do something like this:
void func(GrandChild &gc)
{
int DataFromTheGranChild = gc.DataFromGrandChild;
int DataFromTheChild = gc.Child.DataFromChild;
int DataFromTheParent = gc.Child.Parent.DataFromParent;
int DataFromTheGradParent = gc.Child.Parent.GrandParent.DataFromGrandParent;
//..
}
You could try to only use one type of struct.
struct Entity{
int Data;
Entity* Child;
Entity* Parent;
};

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?

implement a IntStack with bridge pattern in C++

This question was from "Thinking in C++" Vol-1, Chapter 5's exercise No.14:
Create a StackOfInt class (a stack that holds ints) using the
“Cheshire cat” technique that hides the low-level data structure you
use to store the elements in a class called StackImp. Implement two
versions of StackImp: one that uses a fixed-length array of int, and
one that uses a vector. Have a preset maximum size for the stack
so you don’t have to worry about expanding the array in the first
version. Note that the StackOfInt.h class doesn’t have to change with
StackImp.
Here is the header file (StackOfInt.h) I created:
#ifndef STACKOFINT_H
#define STACKOFINT_H
class StackOfInt
{
int size;
int curr_idx;
class StackImp;
StackImp* head;
public:
void initialize(int max);
void push(void* dat);
void* peek();
void* pop();
void cleanup();
};
#endif
However, for the implementation, I'm confused about how to handle the difference between array and vector. Here is what I came up with so far:
#include "StackOfInt.h"
#include "require.h"
#include <vector>
class StackOfInt::StackImp
{
int arrInt[50];
public:
void initialize()
{
for (int i = 0; i < 50; i++)
{
arrInt[i] = 0;
}
}
};
/*
class StackOfInt::StackImp
{
std::vector<int> vecInt;
}
*/
void StackOfInt::initialize(int max)
{
size = max;
curr_idx = 0;
head = 0;
StackImp* newImp = new StackImp;
newImp->initialize();
}
void StackOfInt::push(void* dat)
{
*(head+curr_idx) = dat;
curr_idx++;
}
void* Stack::peek(int idx)
{
require(head != 0, "Stack empty");
return head[idx];
}
void Stack::cleanup()
{
require(head == 0, "Stack not empty");
} ///:~
I think I'm on the wrong tracks, could anyone give me some hints on how to solve this problem?
What the book author has in mind, is that the StackOfInt class should not contain any other members besides a pointer to the implementation class. The necessary data members, be it an array + count variable or a vector, should be members of the implementation class.
So in the header, you'd have
class StackOfInt {
class StackImp;
StackImp* impl;
public:
void initialize();
void push(int dat);
int peek();
int pop();
void cleanup();
};
In the implementation file you'd have the implementation:
class StackOfInt::StackImp
{
public:
int count;
int array[100];
};
void StackOfInt::initialize()
{
impl = new StackImp;
impl->count = 0;
}
void StackOfInt::push(int dat)
{
impl->array[impl->count++] = dat;
}
//and other methods
Write another cpp file that uses the StackOfImp class. Compile the project and run the program to make sure everything works nicely :)
Now you can completely rewrite the implementation file for the StackOfInt to use a vector as the underlying type. Recompile the project. Note that the user of StackOfImp (the test code) does not have to be recompiled because nothing was changed in the header.
To read more about the technique that the author calls "Cheshire cat": Opaque pointer
Note that I don't understand your usage of void pointer. A StackOfInt should take and return integers.
Calling the implementation pointer head also seems to indicate some misunderstanding. This represents a pointer to the object that will actually contain the necessary members to implement the stack.
One way of handling that is to make the "impl" class polymorphic and use a factory to select the implementation at construction time.
I think the expectation is that you will have two different implementations in two separate cpp files, and you would include one or the other in the project in order to use it.
StackImplArr.cpp
class StackOfInt::StackImp
{
int arrInt[50];
}
StackImplVec.cpp
class StackOfInt::StackImp
{
std::vector<int> vecInt;
}
A more advanced use would declare a base class and derive the two implementations from it, allowing the implementation to be selected at runtime:
class StackOfInt::StackImp
{
virtual initialize() = 0;
}
class StackOfInt::StackImpArr : public StackOfInt::StackImp
{
int arrInt[50];
virtual initialize() { ... }
}
class StackOfInt::StackImpVec : public StackOfInt::StackImp
{
std::vector<int> vecInt;
virtual initialize() { ... }
}
void
StackOfInt::initialize( int max) {
head = condition ? new StackImpArr() : new StackImpVec();
}

Beginner and C++ templates: Is it an how possible using C++ template make a class oriented to work with chars work with costume structures?

So I am quite wary new to C++ and I really do not understand templates and how to use tham thow I rad wikipedia and started reading like 2000 pages long book on C++... So I am probably way 2 impatient but I wonder If using C++ templates we can make for example such simple class pair work with costume structures instead of chars.
#include <iostream>
#include <vector>
// Boost
#include <boost/thread.hpp>
#ifndef _IGraphElementBase_h_
#define _IGraphElementBase_h_
#pragma once
using namespace std ;
class IGraphElementBase {
public:
boost::thread GraphWorker;
mutable boost::mutex GraphItemMutex;
boost::condition_variable GraphItemMutexConditionVariable;
int SleepTime;
// Function for preparing class to work
virtual void Init(){ SetSleepTime(1);}
void SetSleepTime(int timeMS)
{
SleepTime = timeMS;
}
// Function for data update // word virtual makes it possible to overwrite it
virtual void updateData(){}
void StartThread()
{
GraphWorker = boost::thread(&IGraphElementBase::Call, this);
}
virtual void CleanAPI(){}
virtual void Clean()
{
GraphWorker.interrupt();
GraphWorker.join();
CleanAPI();
}
virtual void CastData(){}
//Here is a main class thread function in infinite loop it calls for updateData function
void Call()
{
try
{
for(;;){
boost::this_thread::sleep(boost::posix_time::milliseconds(SleepTime));
boost::mutex::scoped_lock lock(GraphItemMutex);
boost::this_thread::interruption_point() ;
updateData();
lock.unlock();
CastData();
GraphItemMutexConditionVariable.notify_one();
}
}
catch (boost::thread_interrupted)
{
// Thread end
}
}
};
#endif // _IGraphElementBase_h_
#include "IGraphElementBase.h"
#ifndef _IGraphElement_h_
#define _IGraphElement_h_
using namespace std ;
class IGraphElement : public IGraphElementBase{
// We should define prototype of functions that will be subscribers to our data
typedef void FuncCharPtr(char*, int) ;
public:
struct GetResultStructure
{
int length;
char* ptr;
};
// initGet sets up a pointer holding a copy of pointer of data we want to return on Get() call
void InitGet(char * pointerToUseInGetOperations, int pointerToUseInGetOperationsSize)
{
pointerToGet = pointerToUseInGetOperations;
pointerToGetSize = pointerToUseInGetOperationsSize;
}
// Function for adding subscribers functions
void Add(FuncCharPtr* f)
{
FuncVec.push_back(f);
}
// Returns pointer to copy of current graphItem processed data
GetResultStructure Get()
{
boost::mutex::scoped_lock lock(GraphItemMutex);
char * dataCopy = new char[pointerToGetSize];
memcpy (dataCopy,pointerToGet,pointerToGetSize);
lock.unlock();
GraphItemMutexConditionVariable.notify_one();
GetResultStructure result;
result.ptr = dataCopy;
result.length = pointerToGetSize;
return result;
}
void Clean()
{
GraphWorker.interrupt();
GraphWorker.join();
CleanAPI();
//delete[] pointerToGet;
//pointerToGet = 0;
}
// Cast data to subscribers and clean up given pointer
void CastData(){
for (size_t i = 0 ; i < FuncVec.size() ; i++){
char * dataCopy = new char[pointerToGetSize];
memcpy (dataCopy,pointerToGet,pointerToGetSize);
FuncVec[i] (dataCopy, pointerToGetSize) ;}
}
// Cast given data to subscribers and clean up given pointer
void CastData(char * data, int length){
for(size_t i = 0 ; i < FuncVec.size(); i++){
char* dataCopy = new char[length];
memcpy(dataCopy, data, length);
FuncVec[i](dataCopy, length);
}
}
private:
// Char pointer to hold a copy of pointer of data we want to return on Get() call
char* pointerToGet;
int pointerToGetSize;
// Vector to hold subscribed functions
vector<FuncCharPtr*> FuncVec ;
};
#endif // _IGraphElement_h_
So what is most intresting for me in that classes in short:
- typedef void FuncCharPtr(char*, int) ;
- vector<FuncCharPtr*> FuncVec ;
- functions like void CastData(char * data, int length)
It is really wary intresting for me if it is possile to somehow using templates make my classes work with costume structures. So Is it possible and how to do such thing?
Templates are a parameterization of a class. That is, instead of having a bunch of different classes such as
class myclass_int
{
int x;
}
class myclass_double
{
double x;
}
etc...
if you can see the pattern, the only thing different is the type used, SO, we will use an abstract type called a template as a sort of place holder,
class myclass_T
{
T x;
}
THIS CLASS IS NOT A SINGLE CLASS BUT A WHOLE COLLECTION. If we replace T with int we get the first class and T with double we get the second.
But when we instantiate myclass_T we must then specify what T actually is(is it in an int, double, etc..)?
so we will define this parameterized class as
template <typename T>
class myclass
{
T x;
}
And use T as it we already new what it really was.
That one class represents all the possible classes you could make up that had specific types used(I gave 2 instances at the start).
Templates simply make it easier to define such classes. There are a lot more to it than that but it is the foundation of why they are useful. The way to think of a templated class is not as a class but as a "Super class". That is, a class that has the ability to take on different representations.
It's not a difficult concept BUT if you don't have a lot of experience with oop you might not really see why they are useful and think they make things more complex. But once you end up having to write very many similar classes that all only differ by the types used then you'll see why they are so useful(they are actually quite powerful because they end up being able to do a lot more).