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();
}
Related
I'm working on a call center call queue simulation model. I've created a vector of caller objects and assigned them exponential distributed random inter-arrival times, then assigned calculated arrival times in the call center class. I would like to then copy each caller object into a vector priority queue, however I keep receiving this error when i push a caller vector object into the queue:
Error C2280 'Caller::Caller(const Caller &)': attempting to reference a deleted function
I've been trying to fix it for a while now and cannot seem to figure out what is causing the issue or how to fix it. I'm trying to push an already created object, so I'm not sure why I would get a reference to a deleted function. Any help would be appreciated.
My Caller.h file
#pragma once
#include <random>
#include <time.h>
using namespace std;
class Caller
{
private:
bool isPaid;
int priority;
double arrivalTime;
double iarrivalTime;
default_random_engine e1;
random_device rd1;
public:
Caller();
Caller(bool p);
void setPriority();
int getPriority();
void generateInterArrivalTime();
double getInterArrivalTime();
void setArrivalTime(double t);
double getArrivalTime();
};
My Caller.Cpp file
#include "Caller.h"
Caller::Caller() : isPaid(false), priority(0), iarrivalTime(0), arrivalTime(0)
{
}
Caller::Caller(bool p): isPaid(false), priority(0), iarrivalTime(0)
{
isPaid = p;
}
void Caller::setPriority()
{
if (isPaid == true)
{
priority = 1;
}
else(priority = 0);
}
int Caller::getPriority()
{
return priority;
}
void Caller::generateInterArrivalTime()
{
e1.seed(rd1());
exponential_distribution<>callNums(25);
iarrivalTime = callNums(e1);
}
double Caller::getInterArrivalTime()
{
return iarrivalTime;
}
void Caller::setArrivalTime(double t)
{
arrivalTime = t;
}
double Caller::getArrivalTime()
{
return arrivalTime;
}
My CallCenter.h file
class CallCenter
{
private:
vector<Caller> callers;
priority_queue<Caller, vector<Caller>, CompareFunction > callQ;
public:
CallCenter();
void queueCalls();
void assignArrivalTime();
My CallCenter.Cpp file
CallCenter::CallCenter(): callers(10)
{
}
void CallCenter::assignArrivalTime()
{
for (int i = 0; i < callers.size(); i++)
{
callers[i].generateInterArrivalTime();
if (i==0)
{
callers[i].setArrivalTime(callers[i].getInterArrivalTime());
}
else {callers[i].setArrivalTime(callers[i - 1].getArrivalTime() + callers[i].getInterArrivalTime());}
cout << callers[i].getInterArrivalTime() << "\t" << callers[i].getArrivalTime() << endl;
}
}
void CallCenter::queueCalls()
{
for (int i = 0; i < callers.size(); i++)
{
callQ.push(callers[i]);
}
}
My CompareFunction.h file
#pragma once
#include "Caller.h"
class CompareFunction
{
public: bool operator()(Caller& lowp, Caller& highp)
{
return lowp.getArrivalTime() > highp.getArrivalTime();
}
};
random_device rd1;
Your class has a std::random_device as a class member.
std::random_device's copy constructor is deleted:
The copy constructor is deleted: std::random_device is not copyable
nor movable.
This makes this class, which contains this class member, also have a deleted copy constructor.
After all, if a class member cannot be copied, by default, then the class itself can't be copied by default either.
priority_queue<Caller, vector<Caller>, CompareFunction > callQ;
Your priority queue is based on a std::vector.
callQ.push(callers[i]);
std::vectors cannot be used with non-copyable/movable classes. You can only use std::vector with classes that can be copied or moved.
You will have to change your class design, in some form or fashion. The simplest change would be a priority queue of std::unique_ptrs or std::shared_ptrs to your Callers, which you will need to construct in dynamic scope (you will also have to provide a custom comparator class for std::priority_queue, so it knows how to prioritize the smart pointers correctly, this is a little bit of extra work but it's not too complicated once you have a complete grasp on all the moving pieces).
SO I am trying to teach myself data structures in C++. To do so, I made an ArrayList class with a member variable arrayData with type int* and a get method to access values from that pointer. I come from a Java background and C++ OOP is sorta strange, especially with the separation of header and source files. At compile, I get, "error: 'int* ArrayList::arrayData' is not a static data member of 'class ArrayList'". I marked them with ArrayList:: to make them members of ArrayList, so why does this not mark them as such? Thank you so much if you can point me in the direction of how to access my variable.
ArrayList.cpp:
#include "ArrayList.h"
ArrayList::ArrayList(int size) {
arrayData = new int[size];
}
ArrayList::~ArrayList() {
delete arrayData;
}
int* ArrayList::get(int index) {
return (*(this.arrayData))[index];
}
int* ArrayList::arrayData;
ArrayList.h:
#define ARRAYLIST_H_
class ArrayList {
public:
ArrayList(int size);
~ArrayList();
int get(int index);
private:
int* arrayData;
};
#endif /* ARRAYLIST_H_ */
This line:
int* ArrayList::arrayData;
In the source file makes no sense. Compiler thinks you're referencing a static variable of ArrayList (because you've prepended with the class name). Remove this line.
You will be able to access arrayData from the other methods.
Also, use std::unique_ptr<int> instead of the raw pointer. Then your memory is guaranteed to be automatically released after use.
You have a few errors here.
First, your ArrayList.h include guards are incorrect.
#ifndef ARRAYLIST_H_
#define ARRAYLIST_H_
class ArrayList {
public:
ArrayList(int size);
~ArrayList();
int get(int index);
private:
int* arrayData;
};
#endif /* ARRAYLIST_H_ */
Next, Your int ArrayList::get declaration and definition are inconsistent. There isn't a need for the int* ArrayList::arrayData; in your C++ file as well.
#include "ArrayList.h"
ArrayList::ArrayList(int size) {
arrayData = new int[size];
}
ArrayList::~ArrayList() {
delete arrayData;
}
int ArrayList::get(int index) {
return arrayData[index];
}
I have a bit of a design problem:
I have a class describing a Robot; It can move to different directions, move a camera to different views etc. It looks something like this:
class Robot {
private:
...
public:
void move_right();
void move_left();
void switch_camera()
void raise_camera()
}
I want to add another method which performs a series of events. Thing is, I need able to abort the events midway.
I do want to clarify that the robot is running on a micro controller and not on a standard OS - so I can't really send a signal to the process or anything.
My first idea was to store the event functions in an array and iterate over it:
#typedef void(robo_event *)(void)
robo_event next_event;
robo_event *event_sequence;
Robot() {
this->next_event = nullptr;
}
void perform_event_series() {
for(this->next_event = *event_sequence; this->next_event != nullptr; this->next_event+=sizeof(robo_event)) {
this->next_event();
}
}
void abort_event_series() {
this->next_event = nullptr;
}
Thing is, the c++ standard forbids storing addresses of member functions, so this is starting to get awkward. I can make the functions static, but I do need to use them quite frequently and that would still be awkward. I want to be able to change to event sequence without too much work if changes are yet to come, so I thought that saving those on some sort of array / vector would be the best.
Any help with c++ member function syntax / better ideas on how to approach this problem would be much appreciated.
Thing is, the c++ standard forbids storing addresses of member functions
C++ most certainly allows you to store pointers to member functions (and variables), but the syntax is a bit different to accommodate the this pointer type, virtual functions, inheritance, etc.
class Example
{
public:
double foo(int x) { return x * 1.5; }
};
int main() {
double (Example::* member_function_ptr)(int);
member_function_ptr = &Example::foo;
Example example;
std::cout << (example.*member_function_ptr)(2) << std::endl;
}
If all your functions are for the same class, same return type, same arguments, etc. then you can make a table of them easy enough.
Storing pointers to member functions is perfectly allowable in c++:
#include <vector>
class Robot {
private:
public:
void move_right();
void move_left();
void switch_camera();
void raise_camera();
};
struct Action
{
Action(void (Robot::*what)(void))
: what(what)
{}
void perform(Robot& who) const
{
(who.*what)();
}
void (Robot::*what)(void);
};
bool should_abort();
void perform_actions(Robot& who, std::vector<Action> const& actions)
{
for (auto&& action : actions)
{
if (should_abort()) break;
action.perform(who);
}
}
int main()
{
std::vector<Action> actions {
&Robot::move_right,
&Robot::raise_camera,
&Robot::switch_camera,
&Robot::move_left
};
Robot r;
perform_actions(r, actions);
}
Pointers to functions are of different types to pointers to members.
You need void(Robot::*)(void) not void(*)(void).
class Robot {
private:
typedef void(Robot::*robot_event)(void)
robo_event next_event;
robo_event *event_sequence;
Robot() {
next_event = nullptr;
}
void perform_event_series() {
for(next_event = *event_sequence; next_event != nullptr; ++next_event) {
(this->*next_event)();
}
}
void abort_event_series() {
next_event = nullptr;
}
public:
void move_right();
void move_left();
void switch_camera()
void raise_camera()
}
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).
I need to bind a method into a function-callback, except this snippet is not legal as discussed in demote-boostfunction-to-a-plain-function-pointer.
What's the simplest way to get this behavior?
struct C {
void m(int x) {
(void) x;
_asm int 3;
}};
typedef void (*cb_t)(int);
int main() {
C c;
boost::function<void (int x)> cb = boost::bind(&C::m, &c, _1);
cb_t raw_cb = *cb.target<cb_t>(); //null dereference
raw_cb(1);
return 0;
}
You can make your own class to do the same thing as the boost bind function. All the class has to do is accept the function type and a pointer to the object that contains the function. For example, this is a void return and void param delegate:
template<typename owner>
class VoidDelegate : public IDelegate
{
public:
VoidDelegate(void (owner::*aFunc)(void), owner* aOwner)
{
mFunction = aFunc;
mOwner = aOwner;
}
~VoidDelegate(void)
{}
void Invoke(void)
{
if(mFunction != 0)
{
(mOwner->*mFunction)();
}
}
private:
void (owner::*mFunction)(void);
owner* mOwner;
};
Usage:
class C
{
void CallMe(void)
{
std::cout << "called";
}
};
int main(int aArgc, char** aArgv)
{
C c;
VoidDelegate<C> delegate(&C::CallMe, &c);
delegate.Invoke();
}
Now, since VoidDelegate<C> is a type, having a collection of these might not be practical, because what if the list was to contain functions of class B too? It couldn't.
This is where polymorphism comes into play. You can create an interface IDelegate, which has a function Invoke:
class IDelegate
{
virtual ~IDelegate(void) { }
virtual void Invoke(void) = 0;
}
If VoidDelegate<T> implements IDelegate you could have a collection of IDelegates and therefore have callbacks to methods in different class types.
Either you can shove that bound parameter into a global variable and create a static function that can pick up the value and call the function on it, or you're going to have to generate per-instance functions on the fly - this will involve some kind of on the fly code-gen to generate a stub function on the heap that has a static local variable set to the value you want, and then calls the function on it.
The first way is simple and easy to understand, but not at all thread-safe or reentrant. The second version is messy and difficult, but thread-safe and reentrant if done right.
Edit: I just found out that ATL uses the code generation technique to do exactly this - they generate thunks on the fly that set up the this pointer and other data and then jump to the call back function. Here's a CodeProject article that explains how that works and might give you an idea of how to do it yourself. Particularly look at the last sample (Program 77).
Note that since the article was written DEP has come into existance and you'll need to use VirtualAlloc with PAGE_EXECUTE_READWRITE to get a chunk of memory where you can allocate your thunks and execute them.
#include <iostream>
typedef void(*callback_t)(int);
template< typename Class, void (Class::*Method_Pointer)(void) >
void wrapper( int class_pointer )
{
Class * const self = (Class*)(void*)class_pointer;
(self->*Method_Pointer)();
}
class A
{
public:
int m_i;
void callback( )
{ std::cout << "callback: " << m_i << std::endl; }
};
int main()
{
A a = { 10 };
callback_t cb = &wrapper<A,&A::callback>;
cb( (int)(void*)&a);
}
i have it working right now by turning C into a singleton, factoring C::m into C::m_Impl, and declaring static C::m(int) which forwards to the singleton instance. talk about a hack.