Is this a bad hack? memcpy with virtual classes - c++

Ok, here's some hack I came up with, but I'm having some problems using it in real world code. This is a working example of what I want to do
class VirtualParent
{
public:
virtual void printVal() = 0;
};
class Parent : public VirtualParent
{
public:
virtual void printVal()
{
cout << "Val is: " << val << endl;
}
void SetVal(foo * v) { val = v; }
protected:
foo* val;
};
class Child : public Parent
{
public:
virtual void printVal()
{
cout << "From child, Val is: ";
val->print();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Parent * p_ptr = new Child;
foo * val = new foo;
p_ptr->SetVal(val);
p_ptr->printVal();
for(int n = 0;n < 100;n++)
{
Parent * new_ptr = nullptr;
//memcpy ( &new_ptr, &p_ptr, sizeof(Parent) );
memcpy_s( &new_ptr, sizeof(p_ptr),&p_ptr, sizeof(p_ptr) );
new_ptr->printVal();
}
return 0;
}
This example works if I use memcpy, or memcpy_s. The idea is to pass a user derived class to a function, that then will create several copies, but as I don't know at compile time the derived class type, I thought of that. As I said, that works perfectly, and i copied that to my engine, where i want to use it, and I'm having some memory issues appearing from nowhere, and they seem to be releated to that hack. Using memcpy_s solves some of them.
Is this something "good" to do, or there's a better way?
Here's the "real world" code
_Lua::ScriptedEntity * newScript = EntityBase;//nullptr;
//assert(HeapValidate(GetProcessHeap(),0,nullptr));
//memcpy( &newScript, &EntityBase, sizeof(_Lua::ScriptedEntity) );
memcpy_s(&newScript, sizeof(EntityBase), &EntityBase, sizeof(EntityBase));
//assert(HeapValidate(GetProcessHeap(),0,nullptr));
string luaPath = transforms.next_sibling().next_sibling().first_attribute().as_string();
newScript->CompileFile(luaPath.c_str());
auto callback = [&](_Physics::Trigger* trigger,PxTriggerPair* pairs, PxU32 count)
{
newScript->SelectScriptFunction("TriggerCallback");
newScript->AddParam(trigger->Id);
auto data = (_Physics::RayCastingStats*)pairs->otherShape->userData;
newScript->AddParam((PxU8)pairs->flags);
newScript->AddParam(data->ID);
newScript->AddParam((int)data->Type);
newScript->AddParam((int)count);
newScript->Go(1);
return;
};
((_Physics::Trigger*)EnginePTR->iPhysics->GetPhysicObject(StartingTriggerID))->InternalCallback = callback;
and the class
//class derived from LuaScript, implements a set of common use functions for AI scripts and similar. Used in the XLL parser.
class ScriptedEntity : public LuaScript
{
protected:
static const int NumberOfFunctions = 11;
std::array<function<int(LuaVirtualMachine& vm)>,NumberOfFunctions> FunctionsArray;
int m_iMethodBase;
public:
ScriptedEntity(LuaVirtualMachine& vm) : LuaScript (vm)
{
InternalEntity = new Entity;
m_iMethodBase = RegisterFunction("GetEntityPos");
RegisterFunction("GetPlayerPos");
RegisterFunction("Move");
RegisterFunction("GetEntityLife");
RegisterFunction("IsPlayerVisible");
RegisterFunction("SetOrientationFromLookAt");
RegisterFunction("RotateAxisUp");
RegisterFunction("GetEntityOrientation");
RegisterFunction("Idle");
RegisterFunction("TeleportBehindPlayer");
RegisterFunction("ApplyGravity");
FunctionsArray[0] = [this](LuaVirtualMachine& vm){ return this->GetEntityPos(vm); };
FunctionsArray[1] = [this](LuaVirtualMachine& vm){ return this->GetPlayerPos(vm); };
FunctionsArray[2] = [this](LuaVirtualMachine& vm){ return this->Move(vm); };
FunctionsArray[3] = [this](LuaVirtualMachine& vm){ return this->GetEntityLife(vm); };
FunctionsArray[4] = [this](LuaVirtualMachine& vm){ return this->IsPlayerVisible(vm); };
FunctionsArray[5] = [this](LuaVirtualMachine& vm){ return this->SetOrientationFromLookAt(vm); };
FunctionsArray[6] = [this](LuaVirtualMachine& vm){ return this->RotateAxisUp(vm); };
FunctionsArray[7] = [this](LuaVirtualMachine& vm){ return this->GetEntityOrientation(vm); };
FunctionsArray[8] = [this](LuaVirtualMachine& vm){ return this->Idle(vm); };
FunctionsArray[9] = [this](LuaVirtualMachine& vm){ return this->TeleportBehindPlayer(vm); };
FunctionsArray[10] = [this](LuaVirtualMachine& vm){ return this->ApplyGravity(vm); };
ViewRayCount = 16;
}
virtual int ScriptCalling (LuaVirtualMachine& vm, int iFunctionNumber)
{
if(iFunctionNumber - m_iMethodBase > NumberOfFunctions)
return 0;
else
return FunctionsArray[iFunctionNumber - m_iMethodBase](vm);
// The user might want to add functions to the script, and that's done by overloading this function. That's why it's virtual
}
// Functions
// Prototypes
int GetEntityPos(LuaVirtualMachine& vm);
int GetPlayerPos(LuaVirtualMachine& vm);
int AttackPlayer(LuaVirtualMachine& vm);
int Move(LuaVirtualMachine& vm);
int GetEntityLife(LuaVirtualMachine& vm);
int GetEntityRawDamage(LuaVirtualMachine& vm);
int IsPlayerVisible(LuaVirtualMachine& vm);
int SetOrientationFromLookAt(LuaVirtualMachine& vm);
int RotateAxisUp(LuaVirtualMachine& vm);
int GetEntityOrientation(LuaVirtualMachine& vm);
int Idle(LuaVirtualMachine& vm);
int TeleportBehindPlayer(LuaVirtualMachine& vm);
int ApplyGravity(LuaVirtualMachine& vm);
int ShootPlayer(LuaVirtualMachine& vm);
// Defined
bool Update(float ElapsedTime)
{
SelectScriptFunction("Update");
AddParam(ElapsedTime);
Go(1);
SelectScriptFunction("Clear"); // dummy function to clean the stack
Go();
return InternalEntity->Alive;
}
void HandleReturns (LuaVirtualMachine& vm, const char *strFunc)
{
if(string(strFunc) == "Update")
{
// frames returns an answer of the stack
lua_State *state = (lua_State *) vm;
InternalEntity->Alive = lua_tonumber(state,-1) != 0;
}
}
// Vars
Entity * InternalEntity;
void * EnginePTR_voidptr;
int PhysicID,VisualID,PlayerID;
int ViewRayCount;
};
Also, the memcpy happends inside:
HRESULT LoadSceneSimple(string Path,
int StartingModelID,
int StartingInstanceID,
int StartingEmmitterID,
int CameraID,
int StartingTriggerID,
int StartingMaterialID,
int StartingPhysicsID,
int ShaderID,
void* engPtr,function<void(_X3D::BaseEffect* effect, _X3D::MaterialValues* matt,int ObjectID,int ShaderID)> MaterialCallback,
string subfolder,
_Lua::ScriptedEntity * EntityBase, string LuaSubfolder);

You are just copying a pointer.
Even so, you cant use memcpy the way you are trying to, since you need to know how big the associated memory is (that the pointer is pointing to), which can vary based on the concrete class.
One way to do what you intend is to add a virtual Parent* Parent::clone() function which then gets overriden by Child* Child::clone().
Then you can do something like Parent* new_parent = p_ptr->clone() without needing to know the subclass.
It is assumed that the clone() function would take care of allocating (new) the heap memory for the correct/equivalent type.

Related

Is this member variable used to register subclasses in this protype design pattern? If yes, how?

I am studying this piece of code in the book "Design Patterns explained simply".
It is the implementation of proytpe design pattern by the author Alexander Shvets.
Although I thikn I have undrstand most of it, but the static variable _landSatImage have confued me for several days.
By the comment of the author, it seems to register the subclass.
But how _landSatImage is used to register the subclasses?
Anyone can give me some clue? Thanks :)
#include <iostream>
#include <vector>
using namespace std;
//--------------------- 1 Image
enum imageType
{
LSAT, SPOT
};
class Image
{
public:
virtual void draw() = 0;
static Image *findAndClone(imageType);
protected:
virtual imageType returnType() = 0;
virtual Image *clone() = 0;
// As each subclass of Image is declared, it registers its prototype
static void addPrototype(Image *image)
{
_prototypes[_nextSlot++] = image;
}
private:
static Image *_prototypes[10];
static int _nextSlot;
};
Image *Image::_prototypes[];
int Image::_nextSlot;
// Client calls this public static member function
// when it needs an instance of an Image subclass
Image *Image::findAndClone(imageType type)
{
for (int i = 0; i < _nextSlot; i++)
if (_prototypes[i]->returnType() == type)
return _prototypes[i]->clone();
}
//----------------------- 2 LandSatImage
class LandSatImage: public Image
{
public:
imageType returnType()
{
return LSAT;
}
void draw()
{
cout << "LandSatImage::draw " << _id << endl;
}
// When clone() is called, call the one-argument ctor with a dummy arg
Image *clone()
{
return new LandSatImage(1);
}
protected:
// This is only called from clone()
LandSatImage(int dummy)
{
_id = _count++;
}
private:
// Mechanism for initializing an Image subclass -
// this causes the default ctor to be called,
// which registers the subclass's prototype
static LandSatImage _landSatImage;
// This is only called
// when the private static data member
// is inited
LandSatImage()
{
addPrototype(this);
}
// Nominal "state" per instance mechanism
int _id;
static int _count;
};
// Register the subclass's prototype
LandSatImage LandSatImage::_landSatImage;
// Initialize the "state" per instance mechanism
int LandSatImage::_count = 1;
//------------------------------ 3 SpotImage
class SpotImage: public Image
{
public:
imageType returnType()
{
return SPOT;
}
void draw()
{
cout << "SpotImage::draw " << _id << endl;
}
Image *clone()
{
return new SpotImage(1); //
}
protected:
SpotImage(int dummy)
{
_id = _count++;
}
private:
SpotImage()
{
addPrototype(this);
}
static SpotImage _spotImage;
int _id;
static int _count;
};
SpotImage SpotImage::_spotImage;
int SpotImage::_count = 1;
//----------------------------------------- main
// Simulated stream of creation requests
const int NUM_IMAGES = 8;
imageType input[NUM_IMAGES] =
{
LSAT, LSAT, LSAT, SPOT, LSAT, SPOT, SPOT, LSAT
};
int main()
{
Image *images[NUM_IMAGES];
// Given an image type, find the right prototype, and return a clone
for (int i = 0; i < NUM_IMAGES; i++)
images[i] = Image::findAndClone(input[i]);
// Demonstrate that correct image objects have been cloned
for (int i = 0; i < NUM_IMAGES; i++)
images[i]->draw();
// Free the dynamic memory
for (int i = 0; i < NUM_IMAGES; i++)
delete images[i];
}

how do i initialize a public variable in a public class method

I have a public class in which I create an array, this array takes its size from the constructor and needs to be used in other functions (including int main). Therefore the variable must be public. my code looks something along these lines:
class myclass {
public:
int parameter1;
int parameter2;
myclass(int p, int p2) {
parameter1 = p;
parameter2 = p2;
}
void makeArray() {
int array[parameter1][parameter2]; //I want this array to be public as the next method needs access to it
}
void otherFunction() {
array[1][2] = 5; //just an example of what i need to do
}
}
Look up how to use pointers and dynamic memory..
To do what you want would be something like:
class myclass {
public:
int parameter1;
int parameter2;
int **a;
myclass(int p, int p2) {
parameter1 = p;
parameter2 = p2;
a = nullptr;
}
~myclass() {
// TODO: delete "a"
}
void makeArray() {
// TODO: delete "a" if it has already been allocated
a = new *int[parameter1];
for (int i = 0; i < parameter1; ++i) {
a[i] = new int[parameter2];
}
}
void otherFunction() {
// TODO: check that "a" has already been allocated
a[1][2] = 5; //just an example of what i need to do
}
}
You could also allocate the array in the constructor since you have the necessary information being passed in already.
This is more optimized way to do the same thing:
class myclass {
public:
int parameter1;
int parameter2;
int *array;
myclass(int p1, int p2) {
parameter1 = p1;
parameter2 = p2;
}
void makeArray() {
array = new int[parameter1*parameter2];
}
void otherFunction() {
// ary[i][j] is then rewritten as ary[i*sizeY+j]
array[1*parameter2+2] = 5;
}
};
int main()
{
int sizeX = 5;
int sizeY = 5;
myclass m1(sizeX,sizeY);
m1.makeArray();
m1.otherFunction();
cout << m1.array[1*sizeY+2] << endl;
return 0;
}

Builder design pattern does not work for me

I have a problem with a c++ code I just written. The code is a sample of the Builder design pattern. I created an abstract builder class, and two classes inherited from this class: MonsterBuilder and RuffianBuilder. I created a Builder class, this class receives a Monster or a RuffianBuilder, and constructs a new instance of these classes. The problem comes here: if the MonsterBuilder class is used to build a new instance the program terminates with an error (a.exe has stopped working). If the Builder receives a RuffianBuilder, it constructs a new instance without an error. Here is the sample code:
#include <iostream>
class Character
{
private:
// Attributes
int dex;
int str;
int end;
// skills
int lockpick;
int guns;
int sneak;
/***************************************** Setters ********************************************************/
// Attribute setters
public:
void setStrength(const int &s)
{
this->str = s;
}
void setDexterity(const int &d)
{
this->dex = d;
}
void setEndurance(const int &e)
{
this->str = e;
}
// Skill setters
void setLockpick(const int &s)
{
this->lockpick = s;
}
void setSneak(const int &s)
{
this->sneak = s;
}
void setGuns(const int &s)
{
this->guns = s;
}
int getGuns()
{
return this->guns;
}
int getStrength()
{
return this->str;
}
};
/* Abstract builder */
class CharacterBuilder
{
protected:
Character * int_character;
public:
Character * getCharacter()
{
return int_character;
}
void buildCharacter()
{
int_character = new Character;
}
virtual void buildSkills() = 0;
virtual void buildAttributes() = 0;
};
class MonsterBuilder : public CharacterBuilder
{
public:
virtual void buildSkills()
{
int_character->setLockpick(10);
int_character->setSneak(12);
int_character->setGuns(50);
}
virtual void buildAttributes()
{
int_character->setStrength(5);
int_character->setDexterity(5);
int_character->setEndurance(5);
}
};
class RuffianBuilder : public CharacterBuilder
{
public:
virtual void buildSkills()
{
int_character->setLockpick(10);
int_character->setSneak(12);
int_character->setGuns(50);
}
virtual void buildAttributes()
{
int_character->setStrength(5);
int_character->setDexterity(5);
int_character->setEndurance(5);
}
};
class Builder
{
public:
void setBuilder(CharacterBuilder * builder)
{
this->builder = builder;
}
Character * getCharacter()
{
return builder->getCharacter();
}
void buildCharacter()
{
//std::cout << builder->buildSkills;
builder->buildSkills();
builder->buildAttributes();
}
private:
CharacterBuilder * builder;
};
int main()
{
Builder B;
RuffianBuilder R;
MonsterBuilder Mo;
B.setBuilder(&R);
B.buildCharacter();
std::cout << B.getCharacter()->getGuns();
std::cout << B.getCharacter()->getStrength();
B.setBuilder(&Mo);
B.buildCharacter();
//std::cout << B.getCharacter()->getStrength();
return 0;
}
What causes this problem? Could somebody explain it?
Reading uninitlalized variable will cause undefined behavior.
I added builder->buildCharacter(); to Builder::buildCharacter() and then this code seems working well.
class Builder
{
public:
void setBuilder(CharacterBuilder * builder)
{
this->builder = builder;
}
Character * getCharacter()
{
return builder->getCharacter();
}
void buildCharacter()
{
//std::cout << builder->buildSkills;
builder->buildCharacter(); // add this line
builder->buildSkills();
builder->buildAttributes();
}
private:
CharacterBuilder * builder;
};

I can't display variables of different types included in array

I have to do a program for college.
I have 3 classes already declared in the statement of the problem.
First class:
class piesa_a{
protected:
int id;
char *tip;
int pret;
};
Second class:
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
};
Third class:
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
};
In main I need to create an array in which to store items such piesa_a, piesa_b, piesa_c. Then I have to sort items by price.
I have this code so far: http://pastebin.com/nx2FGSfe
The program is incomplete because it does not displays each item in the array.
I got stuck here. But if you display the array's elements when they are outside of it, it works.
SHORT: I have an error on line 143 and I want to solve it.
main.cpp:143:18: error: request for member ‘afisare’ in ‘*(v + ((unsigned int)(((unsigned int)i) * 4u)))’, which is of non-class type ‘piesa_a*’
The code is here:
#include <cstdlib>
#include<iostream>
#include<string.h>
using namespace std;
class piesa_a{
protected:
int id;
char *tip;
int pret;
public:
piesa_a()
{
id = 0;
tip = new char[1];
pret = 0;
}
piesa_a(int aidi, char *typ, int pretz)
{
id = aidi;
tip = new char[strlen(typ)+1];
strcpy(tip,typ);
pret = pretz;
}
piesa_a&operator =(piesa_a alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
return *this;
}
virtual void afisare()
{
cout<<"\n Piesa A: "<<id<<" "<<tip<<" "<<pret;
}
};
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
public:
piesa_b():piesa_a(){lungime = 0;bw = 0;}
piesa_b(float lg,bool bl, int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
lungime = lg;
bw = bl;
}
piesa_b&operator =(piesa_b &c)
{
id = c.id;
tip = new char[strlen(c.tip)+1];
strcpy(tip,c.tip);
pret = c.pret;
lungime = c.lungime;
bw = c.bw;
return *this;
}
void afisare()
{
piesa_a::afisare();
cout<<"impreuna cu piesa B: "<<lungime<<" "<<bw<<"\n";
}
};
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
public:
piesa_c():piesa_a(){nr=0; buf = new piesa_b[nr];}
piesa_c(int n, piesa_b *bu,int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
nr = n;
buf = new piesa_b[nr];
for(int i=0;i<nr;i++)
buf[i]= bu[i];
}
piesa_c&operator =(piesa_c &alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
nr = alta.nr;
for(int i=0;i<alta.nr;i++)
buf[i] = alta.buf[i];
}
void afisare()
{
for(int i=0;i<nr;i++)
buf[i].afisare();
}
};
int main(int argc, char** argv) {
piesa_b *H;
H = new piesa_b[2];
piesa_a A(4,"TIPA",120);
piesa_b B(100,1,3,"TIPA",120);
H[0]=B;
H[1]=B;
piesa_c C(2, H,14,"TIPC",20);
piesa_a** v = new piesa_a*[3];
v[0] = &A;
v[1] = &B;
v[2] = &C;
for(int i=0;i<3;i++)
v[i].afisare();
return 0;
}
What's wrong?
In C++ (and current C), casts are almost always a sign that the programmer didn't know how to use the language as it is supposed to be used. If you need an array of 3 types of data, the cleanest solution is an array of objects of a class that is base to the 3. And if you want to display each item differently, you'll want to overload the << operator, so you just iterate over the array and go << on each item. Sorted by price means that the class includes a price field, and you use the sort from the standard template library, passing a comparison operation that just compares prices.

Automatically decide which class to use for data processing

I have a big project where I faced a problem, which can be shortly formulated as following:
I had a class which is created temporally and used to process and modify some data (let's call it "worker"). Now I have two workers and two corresponding data formats. The data array can contain mixed data, how to make my programm automatically decide which worker class it should create and use for data processing? How to make this in the best way?
To illustrate this problem I wrote small example programm, which is analogical to my project.
#include <iostream>
#include <vector>
using namespace std;
const int NInputs = 10;
struct TOutput {
int i;
};
class TProcess {
public:
TProcess( const vector<TInput>& i ){ fInput = i; }
void Run();
void GetOutput( TOutput& o ) { o = fOutput; }
private:
vector<TInput> fInput;
TOutput fOutput;
};
#if 0
struct TInput {
int i;
};
class TWorker{
public:
void Init( int i ) { fResult = i; }
void Add( int i ) { fResult += i; }
int Result() { return fResult; }
private:
int fResult;
};
#else
struct TInput {
int i;
};
class TWorker {
public:
void Init( int i ) { fResult = i; }
void Add( int i ) { fResult ^= i; }
int Result() { return fResult; }
private:
int fResult;
};
#endif
void TProcess::Run() {
TWorker worker;
worker.Init(0);
for( int i = 0; i < fInput.size(); ++i )
worker.Add(fInput[i].i);
fOutput.i = worker.Result();
}
int main() {
vector<TInput> input(NInputs);
for ( int i = 0; i < NInputs; i++ ) {
input[i].i = i;
}
TProcess proc(input);
proc.Run();
TOutput output;
proc.GetOutput(output);
cout << output.i << endl;
}
The example is very simple, but that doesn't means that it's simply possible to transform it to one function --- it corresponds to big project. Therefore it is not possible to:
delete classes or functions, which already exists (but possible to modify them and create new)
make workers static or create only one copy of worker (each workers are temporary in many complicated functions and loops)
So how to modify it such that this will be something like this:
// TODO: TProcess declaration
struct TInput1 {
int i;
};
class TWorker1{
public:
void Init( TInput1 i ) { fResult = i; }
void Add( TInput1 i ) { fResult += i.i; }
int Result() { return fResult; }
private:
int fResult;
};
#else
struct TInput2 {
int i;
};
class TWorker2 {
public:
void Init( TInput2 i ) { fResult = i.i; }
void Add( TInput2 i ) { fResult ^= i.i; }
int Result() { return fResult; }
private:
int fResult;
};
void TProcess::Run() {
for( int i = 0; i < fInput.size(); ++i ) {
// TODO: choose and create a worker
worker.Add(fInput[i].i);
// TODO: get and save result
}
fOutput.i = worker.Result();
}
int main() {
vector<TInputBase> input(NInputs);
// TODO: fill input
TProcess proc(input);
proc.Run();
TOutput output;
proc.GetOutput(output);
cout << output.i << endl;
}
My initial idea was to use basic class and template functions, but there is no template virtual functions...
You've got the right idea with the vector<TInputBase> declaration in your second example -- you need to have a common base class for all inputs, and similarly for all workers:
class TInput {
}
class TInput1 : public TInput { ... }
class TInput2 : public TInput { ... }
class TWorker {
public:
void Init(TInput *input) = 0;
void Add(TInput *input) = 0;
int Result() = 0;
}
class TWorker1 : public TWorker { ... }
class TWorker2 : public TWorker { ... }
Note, however, that this means all workers can only take a TInput * as input and you will need to cast to the correct input class inside each worker class.
The simplest way to decide which worker class to use for a given input is to ask the input itself! You can have a virtual function in the input class that creates the right kind of worker:
class TInput {
virtual TWorker *createWorker() = 0;
}
class TInput1 : public TInput {
TWorker *createWorker() {
return new TWorker1();
}
}
class TInput2 : public TInput {
TWorker *createWorker() {
return new TWorker2();
}
}
If this is not possible for some reason, you can use typeid to determine the type of the input and create a corresponding worker instance.