C++ pass derived struct to method expecting the super struct - c++

I am trying to create a menu library for arduino with C++ and OOP.
I have a struct called:
struct MenuItem {
int position;
String name;
MenuItem(int position, String name) : position(position), name(name) { };
};
And I have a derived struct called:
struct SpecificMenuItem : MenuItem {
int count;
SpecificMenuItem(int position, String name, int count) : MenuItem(position, name) , count(count) { };
};
How can I pass an array of the SpecificMenuItem structs to a method that expects an array of MenuItem? The idea here is that all the derived structs from MenuItem should have position and name, so that a simple list can be rendered out with the following method from the Menu class:
Menu::Menu() {
}
void Menu::setMenuItems(MenuItem *menuItems) {
this->mMenuItems = menuItems;
}
void Menu::render(void) {
for (int j = 0; j < this->mMenuItemSize; j++) {
Serial.println(this->mMenuItems[j].name);
}
}
The header file for specific_menu.h:
class SpecificMenu : public Menu {
struct SpecificMenuItem mSpecificMenuItem[2] = {
{1, "Name", 3},
{2, "Name 2", 4}
};
public:
SpecificMenu();
};
The cpp file for specific_menu.cpp:
SpecificMenu::SpecificMenu() : Menu() {
this->setMenuItems(this->mSpecificMenuItem);
this->setMenuItemsSize(2);
}
The issue right now is that having the extra count member in the SpecificMenuItem struct is causing the program to crash, however the program runs fine if I remove the count member, but I think this is just a fluke that it works. Would love to get some pointers on how to get the above to work.
Cheers!

You cannot pass an array of SpecificMenuItem to a method waiting for an array of MenuItem, even if SpecificMenuItem inherits from MenuItem.
One possible way would be to remove the setMenuItems methods and makes use of polymorphism to access the size and the items of the menu:
class Menu {
protected:
virtual size_t size () const = 0;
virtual MenuItem& operator[] (size_t) = 0;
};
class SpecificMenu : public Menu {
SpecificMenuItem mSpecificMenuItem[2] = {
{1, "Name", 3},
{2, "Name 2", 4}
};
protected:
virtual size_t size () const { return 2; }
virtual const MenuItem& at (size_t i) const {
return mSpecificMenuItem[i];
}
public:
SpecificMenu();
};
And then use these method in Menu::render:
void Menu::render(void) {
for (int j = 0; j < this->size(); j++) {
Serial.println(this->at(j).name);
}
}
This is making your Menu acts as a (abstract) container of "MenuItem&".

You'd better declare something like:
typedef std::list<MenuItem *> MenuItemArray;
Then you can access you base classes by pointer.
void
Menu::setMenuItems(const MenuItemArray& menuItems)
{
this->mMenuItems = menuItems;
}
void
Menu::render(void)
{
for (int j = 0; j < this->mMenuItems.size(); j++) {
Serial.println(this->mMenuItems[j]->name);
}
}
Afterward, if you need to access a SpecificMenuItem element:
...
SpecificMenuItem *specificItem = dynamic_cast<SpecificMenuItem *>(mMenuItems[i]);
if (specificItem) {
...
}
The solution you initialy wrote rather looks like a C solution, not C++ IMHO.
Have fun.

Your problem is, you can't put different structs/classes in same array, as they have different sizes. Consider making array of pointers, that point to objects of base class, as they can point to derived as well. Like
typedef MenuItem * MenuItemPtr;
typedef MenuItemPtr * MenuItemPtrArray;
MenuItemPtrArray myArr= new MenuItemPtr[2];
myArr[1] = new MenuItem(/*...*/);
myArr[2] = new SpecificMenuItem(/*....*/);
Of course, you can use std::list or other collectionas #Holt suggested in his answer, and it would be better solution. But I suppose you don't have it as you write for arduino, which has no stl

Related

how to declare variables based on other params in C++

I have the below code (eg):
void Foo(int ip_selector)
{
ipv4_hdr_t ipv4;
ipv6_hdr_t ipv6;
{
…
if(ip_selector == 0)
addStack(ipv4);
else
addStack(ipv6);
}
{
…
if(ip_selector == 0)
addStack(ipv4);
else
addStack(ipv6);
}
…
}
int main()
{
for (int i = 0; i < 2; i++) {
Foo(i);
}
}
In the above code, addStack param depends on the selector param in Foo(). The above code works fine, but does to the scale it can grow, I do not want to add if ip_selector check everywhere in Foo() to see which arg to be passed in addStack(). I am trying to find a way to select either ipv4_hdr_t/ipv6_hdr_t without writing an if else condition. Infact, I dont even need the ipv6 declaration of ip_selector is 0 (vice versa for that matter)
here is one way to solve such a problem.
1.have a base class for your protocols, say Protocol.
2.derive your ip4/ip6/whateverelse classes from the base class.
3.create an array of available protocols.
4.use the selector to pick an array element.
class Protocol {
virtual void addStack() = 0;
...
};
class Ip4Protocol : public Protocol {
ip4_hdr_type hdr;
void addStack(){...}
};
vector<Protocol*> availableProtocols = {
new Ip4Protocol(),
new IP6Protocol(),
...
};
...
for (int i = 0; i < availableProtocols.size(); i++) {
avalableProtocols[i]->addStack();
}
or you can probably use templates on the derived classes as well
termplate <class P> class IP : public Protocol {
P hdr;
void addStack() {addGlobalStack(hdr)};
}
ther are tons of other possibilities as well.

Better way to store inherited class to the file

This code works, but what is the correct way of doing this?
I mean, how can I eliminate the switch statement in read_in function, or to handle all reading in animal class, or its sub-classes, so my read_in function can be as simple as my write_out function?
I have a vector<animal*> *animals filled with cats and generic animals that I need to write/read to/from a file.
I have omitted some code, so the post doesn't get too big...
enum class animal_type
{
GENERIC_ANIMAL,
CAT
};
Suppose I have a class animal
class animal
{
animal_type m_type;
string m_name;
virtual void write_binary(ofstream &out)
{
out.write((char*)(&m_type), sizeof(m_type)); //first 'animal_type'
out.write((char*)(&m_type), sizeof(m_type)); //second 'animal_type'
out.write(m_name.c_str(), m_name.size()+1);
{
virtual void read_binary(std::ifstream &in)
{
in.read((char*)(&m_type), sizeof(m_type)); //read the second animal type here
m_name = read_null_string(in);//this function returns next string from input
}
};
and a class that derives from animal
class cat : public animal
{
bool m_is_cute;
void write_binary(std::ofstream &out)
{
animal::write_binary(out);
out.write((char*)(&m_is_cute), sizeof(m_is_cute));
}
void read_binary(std::ifstream &in)
{
animal::read_binary(in);
in.read((char*)(&m_is_cute), sizeof(m_is_cute));
}
};
I write them to a file like this
void write_out(std::ofstream &out, std::vector<animal*> *animals)
{
int size = animals->size();
out.write((char*)(&size), sizeof(size));
for(animal* a : *animals)
{
a->write_binary(out);
}
}
And read them from the file like this
void read_in(std::ifstream &in, std::vector<animal*> *animals)
{
animals->clear();
int size;
in.read((char*)(&size), sizeof(size));
for(int i = 0; i< size; ++i)
{
animal_type type;
//read the first 'animal_type' here
in.read((char*)(&type), sizeof(type));
animal *a;
switch(type)
{
case(animal_type::GENERIC_ANIMAL):
a = new animal(in);//this constructor just calls the read_binary method
break;
case(animal_type::CAT):
a = new cat(in);//this constructor just calls the read_binary method
break;
}
animals->push_back(a);
}
}
Here is one (of many) options:
First, we change enum class animal_type to a plain old enum becaysuse we want to use it as an integer. If this is not allowed, leave it enum class animal_type and use a static_cast<size_t> to convert it later.
enum animal_type
{
GENERIC_ANIMAL = 0, // must be 0. First index in array
CAT,
LAST, // must be last. Put no animals after it
FIRST = GENERIC_ANIMAL // makes it easy to loop FIRST to LAST
};
Then define all of your animals.
Next, build an array of functions that call the appropriate animal constructors. This array must exactly match the enum above. If this is a concern, consider using std::map instead.
std::function<animal *(std::ifstream &)> animalFactory[] =
{
[](std::ifstream & in) {return new animal(in);},
[](std::ifstream & in) {return new cat(in);}
};
Documentation on std::function
Documentation on Lambda expressions
Next define exceptions to be thrown should bad things happen. The could be as simple as
class Bogus_File_Exception: public std::exception
{
const char* what() const
{
return "File read failed.";
}
};
Finally read_in becomes
void read_in(std::ifstream &in, std::vector<animal*> & animals) // note the reference
{
animals.clear();
int size;
if (in.read((char*)(&size), sizeof(size))) // testing for successful read
{
for(int i = 0; i< size; ++i)
{
animal_type type;
if (in.read((char*)(&type), sizeof(type))) // testing again
{
if (type < animal_type::LAST)
{
animals.push_back(animalFactory[type](in));
}
else
{
throw Unknown_Animal_Exception();
}
}
else
{
throw Bogus_File_Exception();
}
}
}
else
{
throw Bogus_File_Exception();
}
}

C++ copying data from an abstract base class pointer?

Let's say you have this:
class foo {
public:
virtual int myFunc() = 0;
///...
virtual bool who() = 0; // don't want to implement this
};
class bar : public foo {
public:
int myFunc() {return 3;}
//...
bool who() {return true;} // don't want to implement this
};
class clam : public foo {
public:
int myFunc() {return 4;}
//...
bool who() {return false;} // don't want to implement this
};
int main() {
std::vector<foo*> vec (2, NULL);
vec[0] = new bar();
vec[1] = new clam();
// copy vec and allocate new ptrs as copies of the data pointed to by vec[i]
std::vector<foo*> vec2 (vec.size(), NULL);
for ( int i=0; i<vec.size(); ++i ) {
// obviously not valid expression, but it would be nice if it were this easy
//vec2[i] = new foo(*vec[i]);
// the hard way of copying... is there easier way?
if (vec[i]->who()) {
vec2[i] = new bar ( * static_cast<bar* >(vec[i]) ) ;
} else {
vec2[i] = new clam( * static_cast<clam*>(vec[i]) );
}
}
return 0;
}
What I want is some simple way of having the compiler look up in its bookkeeping and allocating/copying vec2[i] according to the stored type of *vec[i]. The workaround is to just make a virtual function which basically returns a value specifying what type *vec[i] is, then doing a conditional allocation based on that.
A common approach goes like this:
class foo {
public:
virtual foo* clone() = 0;
};
class bar : public foo {
public:
virtual bar* clone() { return new bar(*this); }
};
class clam : public foo {
public:
virtual clam* clone() { return new clam(*this); }
};
One way you can do it is by using a dynamic cast to determine type of an object such as done here (Finding the type of an object in C++). but the easiest way would probably be to use typeid.
(assuming you want to maintain your way of using type as a determiner, otherwise I would recommend Joachim's or Igor's as better alternatives :) )
you can use the dynamic_cast to downcast and test the type,
bar* pbar = dynamic_cast<bar*>(vec[i])
if (pbar) {
vec2[i] = new bar ( * static_cast<bar* >(vec[i]) ) ;
} else {
vec2[i] = new clam( * static_cast<clam*>(vec[i]) );
}
see for more info in dynamic_cast
http://www.cplusplus.com/doc/tutorial/typecasting/

Override array size in subclass

I have an array as a member of a class. In a subclass, I would like to re-define the array with a different size. I want to do this because I anticipate making many subclasses, each with only the array size it needs, and nothing more.
class Foo
{
Foo() {ivar = 1};
int thisArray[2];
int ivar;
}
class Bar : public Foo
{
Bar() {ivar = 3};
int thisArray[4];
}
int main()
{
Foo myFoo;
Bar myBar;
Foo fooCollection[] = {myFoo,myBar};
cout << "myFoo array size = " << sizeof(myFoo.thisArray)/sizeof(int) << endl;
cout << "myBar array size = " << sizeof(myBar.thisArray)/sizeof(int) << endl;
for (int n=0;n<2;n++)
{
cout << "fooCollection[" << n << "] array size = ";
cout << sizeof(fooCollection[n].thisArray)/sizeof(int) << endl;
}
for (int n=0;n<2;n++)
{
cout << "fooCollection[" << n << "] ivar = ";
cout << fooCollection[n].ivar << endl;
}
}
My results are:
myFoo array size = 2
myBar array size = 4
fooCollection[0] array size = 2
fooCollection[1] array size = 2
fooCollection[0] ivar = 1
fooCollection[1] ivar = 3
I get that, since I declare the array objects as objects of class Foo, that referring to myBar within that scope would reference myBar as though it was a Foo and consequently interpret the size of thisArray as equivalent to 2. I also understand why ivar comes out the way it does.
Is there a way to affect the size of thisArray within the Bar class so its "correct" size can be recognized within an array of Foo objects? I would use a vector, but they are not friendly on the arduino platform. I could also simply make the array within the Foo class with a size of 100, but I am trying to be conscious of memory allocation.
You could template your base class:
template <size_t Size>
class FooBase
{
// etc....
int thisArray[Size];
};
class Foo : public FooBase<2> { ... };
class Bar : public FooBase<4> { ... };
Of course, this is only practical where everything derives from FooBase -- that is, you don't have a class that derives from Bar which needs a different array size.
Also, as has been said in comments, if you need to keep these in an array you need to store pointers.
Foo myFoo;
Bar myBar;
Foo * fooCollection[] = { &myFoo, &myBar };
Oops, there I have assumed that Bar derives from Foo, which it no longer does. If you want a common base that isn't templated, you need to derive the templated class FooBase<Size> from another base FooType and now use an array of FooType. I think that will work.
class FooType {
public:
// etc...
virtual size_t GetSize() const = 0;
};
template <size_t Size>
class FooBase : public FooType
{
public:
// etc...
virtual size_t GetSize() const { return Size; }
protected:
// etc....
int thisArray[Size];
};
And then:
FooType *fooCollection[] = { &myFoo, &myBar };
You can define your array as a pointer and then new it with your constructor and delete it in your destructor. Remember the Rule of Three and you will be fine.
This is unless I've totally misunderstood your intent of this program.
When you do this: cout << sizeof(fooCollection[n].thisArray)/sizeof(int) << endl;, it is impossible to know the size of thisArray because you are not using actual polymorphism. So the compiler assumes all elements in fooCollection are simpy Foo (static binding).
Start by using pointers:
Foo * fooCollection[] = { &myFoo, &myBar };
And declaring a virtual member that will know at runtime the size of the array. (dynamic binding)
virtual int size() {return sizeof(thisArray);}
And then rewriting to:
cout << fooCollection[n]->size()/sizeof(int) << endl;
My opinion would be to not allow the base class to be a concrete class:
Let the base class be a abstract class providing interfaces to the
array (size of array, read and write to the array).
Let the construction and destruction of the array be controlled by the
derived classes.
This way, each derived class can choose the length of its array as appropriate.
Code sketch:
class foo {
public:
virtual size_t array_size() const = 0;
virtual int * array_base() const = 0;
int array_get( size_t index ) const {
array_verify_index( index );
return *( array_base() + index );
}
void array_set( size_t index, int value ) {
array_verify_index( index );
*( array_base() + index ) = value;
}
private:
void array_verify_index( size_t index ) const {
assert( index < array_size() );
}
};
class bar : public foo {
public:
bar() {
array_base = new int[ BarArraySize ];
}
~bar() {
delete [] array_base;
}
virtual size_t array_size() const {
return BarArraySize;
}
virtual int * array_base() const {
return array_base;
}
private:
int * array_base;
};
Well aware that I'm two years late, I would like to add another option - for those who seek an answer to this question without virtual methods or the new operator:
class Foo
{
protected:
// Can only be constructed by Bar, or other derived type.
Foo(int* _array, size_t _size) :
array(_array),
arraySize(_size)
{};
private:
int* array;
size_t arraySize;
};
template<size_t Size>
class Bar : public Foo
{
public:
Bar() : Foo(arrayData, Size) {};
private:
int arrayData[Size];
};
This allows Foo to be a common 'array' interface for several classes, with no virtual methods and with stack allocated arrays. Only real drawback is that we, by necessity, inserted Foo::arraySize, but that's still for a relatively small cost (4/8 bytes on 32/64-bit).

Design problems in C++

I have a raw buffer which contains number of different structs(which I couldn't modify) which I planned to wrapped inside a class like below so that I could invoke the virtual Process based on the concrete type.
class Base{
public:
virtual void Process();
};
class DerivedA : public Base {
private:
char* structBuf;
public:
virtual void Process();
}
class DerivedB : public Base {
private:
char* structBuf;
public:
virtual void Process();
}
int main()
{
for(int i = 0 ; i < 10; i++)
{
Base* a = FactoryObject();
a->Process();
}
}
My question is some of the objects depent on each other. For example, let say derivedA data would be processed first and derivedB needs the data from derivedA.
How or where could I store the derivedA object in main() so that I could utilize it in derivedB?
How could I know which objects from factory is derivedA so that I could store it?
Add a constructor to DerivedB that takes a DerivedA parameter. Construct your DerivedB instance only after you processed your DerivedA instance, passing to DerivedB the DerivedA instance.
I think I'm understanding your question.
In main you would have your object that holds the data you want passed around. Have a derivedA public data object (or you can make it private and set it with a set function) and make derivedA.data = main's data. Then when derivedA does its stuff, the object in main will still point to it. Then you repeat the process by handing the data to derivedB with derivedB.data = main's data.
If you make char* structBuf; protected instead of private then all derived classes can access it. As it stands I'm not sure how you'll implement the process function in your derived classes.
It sounds like you're looking for some cache or data-store of already processed information. You could write a class to store this type specific info and then retrieve it in later calls to your virtual process functions. Something like:
class DataCache {
public:
void store( DerivedA* data );
void store( DerivedB* data );
std::list<DerivedA*>& getDerivedA();
std::list<DerivedB*>& getDerivedB();
}
Now your process function should take a reference to a DataCache object, so each call can store and get appropriately. DerivedB might implement process like:
DerivedB::process( DataCache& cache ) {
std::list<DerivedA*>& a_data = cache.getDerivedA();
//do something
cache.store( this );
}
I've interpreted your question as pertaining to reading in a file or stream which has a header section that sets out the subsequent instance definition sections.
#include <iostream>
class AbstractDataProcessor;
class ProcessorFactory
{
public:
static AbstractDataProcessor* create(const char id);
};
class AbstractDataProcessor
{
public:
AbstractDataProcessor() : next_(0) {}
virtual ~AbstractDataProcessor()
{
if(next_ != 0)
{
delete next_;
next_ = 0;
}
}
void process(const char* buf, int size)
{
process(buf, 0, size);
}
protected:
virtual int do_process(const char* buf, int start, int size) = 0;
void append(AbstractDataProcessor* chain)
{
if(next_ == 0)
{
next_ = chain;
}
else
{
next_->append(chain);
}
}
private:
void process(const char* buf, int start, int size)
{
int next_start = do_process(buf, start, size);
std::cout << "AbstractDataProcessor::process: start = " << start << " : size = " << size << " : next_start = " << next_start << std::endl;
if(next_ == 0 || next_start >= size)
{
return;
}
next_->process(buf, next_start, size);
}
AbstractDataProcessor* next_;
};
class HeaderProcessor : public AbstractDataProcessor
{
protected:
static const char header_sentinel = 'H';
virtual int do_process(const char* buf, int start, int size)
{
int current = start;
while(current < size && buf[current] != header_sentinel)
{
std::cout << "HeaderProcessor::do_process: buf[" << current << "] = " << buf[current] << std::endl;
AbstractDataProcessor* section_processor = ProcessorFactory::create(buf[current]);
if(section_processor != 0)
{
append(section_processor);
}
++current;
}
return current + 1;
}
};
class ElementProcessor : public AbstractDataProcessor
{
protected:
int do_process(const char* buf, int start, int size)
{
foo_ = static_cast<float>(buf[start]);
std::cout << "ElementProcessor::do_process: buf[" << start << "] = " << buf[start] << " : foo_ = " << foo_ << std::endl;
return start + (sizeof(float) / sizeof(char));
}
private:
float foo_;
};
AbstractDataProcessor* ProcessorFactory::create(char id)
{
std::cout << "ProcessorFactory::create: id = " << id << std::endl;
switch(id)
{
case 'h':
return new HeaderProcessor;
case 'e':
return new ElementProcessor;
default:
return 0;
}
}
int main(int argc, char** argv)
{
static const int buf_size = 6;
char testbuf[buf_size] = { 'e', 'H', 'x', '3', 't', '[' };
AbstractDataProcessor* testprocessor = ProcessorFactory::create('h');
testprocessor->process(testbuf, buf_size);
return 0;
}
its not the most elegant example, but it illustrates the idea of generating a linked list of processors that act on a single input stream of data. Each processor is capable of appending a new processor as appropriate, you could define another method "AbstractDataProcessor::insert" to allow for implementing a recursive delegation approach within each "do_process" method too. i haven't included any useful extraction methods, but it should be easy enough to walk the linked list and spit out pointers to something in main or wherever you need it.
You could do something like this:
class DerivedA;
class Base{
public:
virtual void Process();
protected:
static std::vector<DerivedA*> dependencies;
};
class DerivedA : public Base {
private:
char* structBuf;
public:
DerivedA() {
dependencies.push_back(this);
}
virtual void Process();
};
class DerivedB : public Base {
private:
char* structBuf;
public:
virtual void Process();
};
int main()
{
std::vector<Base*> allBase;
for(int i = 0 ; i < 10; i++) {
allBase.push_back(FactoryObject());
}
for(int i = 0 ; i < 10; i++) {
allBase[i]->Process();
}
return 0;
}
In short, while the objects are constructed the DerivedA ones are registering themselves in a static vector in Base, which means they are accessible in DerivedB once you are calling Process() on DerivedB types.
You must allow for all derived classes to be created before you can call Process. So, first map and create all and then map again and call Process(). This is of course not optimal since the base knows some about its inherited classes, but you insisted on having this factory pattern.
A better solution is to lift out the static vector from Base and store DerivedA elsewhere. But in the end it will boil down to you having to store DerivedA instances somewhere, and that registration should be done at construction, i.e. in the constructor of DerivedA. I dont know if a simple vector will do as registration, please modify this to suit your needs. For example you might want to look up DerivedA* with some identifier and need a hash or map instead.
Here comes dynamic_cast handy for you. If you have a Base* pointer, you try to do dynamic_cast. If it really is, then the result will be the DerivedA object. Else it is not DerivedA, returns NULL.
So in your main(),
Base* a = FactoryObject();
DerivedA *CheckObj= dynamic_cast<DerivedA*>(a);
DerivedA *AObj = NULL;
if(CheckObj)
{
AObj = CheckObj;
AObj->Process();
}
else
{
if(AObj)
{
AObj->Process();
CheckObj->Process();
}
}