I tried to do a simple factory but ended up with a wierd error?

Started by
24 comments, last by Servant of the Lord 11 years, 3 months ago
Performance question
If this vector that hold my pointers were to be "in game" enemies, would it be better to NOT delete it and simply "re use" it, after the "death timer"/"spawn timer" have been reach?

Well, first, don't try to optimize before it's necessary, or you risk accidentally optimizing all the wrong parts of the code.

But in answer to your question, yes it would be better to not delete it *if* you allocate/deallocate tens of thousands of enemies every frame. Even a few hundred won't hurt anything. Only make such optimizations when you actually encounter a slowdown and after you identify what is causing the slowdown using a profiler.

And is there a good website somewhere that would explain these types of detail? ... oh would also be nice if anyone could give me a good place reading on about the smart pointers seeing they seems to be good thing to know about.


There's no one real website that really covers everything about C++ perfectly, though I do personally find Parashift C++ FAQ very incredibly useful.

For smart pointers, C++'s smart pointers were mostly ported from the Boost C++ libraries, so until good tutorials and documentation arrives for the std::shared_ptr and such, you can read the documentation and tips for boost::shared_ptr.

Boost smart pointer documentation (especially the frequently asked questions)

I wrote a GameDev.net post about smart pointers here

Here's an important performance tip about smart pointers


Everything works now! thanks alot


Glad to hear it! There is one other optional addition you might want, but I didn't want to suggest it while you were still working through the earlier errors.


template<class EntityType, typename... Args>
std::shared_ptr<EntityType> EntityFactory:: InstantiateEntity(Args &&... args)
{
     return std::make_shared<EntityType>(args...);
}


This lets you pass as many parameters as you want to InstantiateEntity(), and InstantiateEntity() will pass them to std::make_shared() (which internally passes them to EntityType's constructor).

The && symbol is called an r-value reference, and lets you get a reference to variables that might be unnamed temporary variables, in the same way & lets you get a reference to named variables. The '...' means we're getting an unknown number of variables.

Putting them together, we get an unknown number of possibly (or possibly not) unnamed temporary variables that we then pass to the class you are constructing, so you can use its constructor parameters even when creating through InstantiateEntity().

Then, instead of just passing the values to std::make_shared, what we actually want is to 'perfectly forward' the values, so that it is as if we passed the variables directly to the constructor itself, instead of going through several functions first.


template<class EntityType, typename... Args>
std::shared_ptr<EntityType> EntityFactory:: InstantiateEntity(Args &&... args)
{
     return std::make_shared<EntityType>(std::forward<Args>(args)...);
}


It makes sure that if we passed any parameters by value, they won't get accidentally passed by value a second time, but instead as a r-value reference.

You can read more of r-value references and std::forward<> here. Page 7 talks exactly about the circumstances you are encountering.

Advertisement

OFFTOPIC, straight ahead!

Miss the simplicity of c# sad.png.

AHAHA! I thought my sharp-jitsu senses were tingling from the 1st implementation. In c# indeed, the behavior is inferred from the type being a value-type or a reference type (and from the fact that the garbage collector sweeps all the time behind your back).

Now, in C++ you have to do all the hand-holding yourself for all your class instances (and if you want to share them around via pointers, you're gonna have a ... good... time ).

The thing is, try to keep it simple and "make up" rules for yourself, like "whoever requests a pointer must also tell me when they don't need it anymore" or " I made you, I'll destroy you" i.e. "who calls new will also call delete".

Also, when learning C++, since you have all the time in the world (yea, right...) my personal advice, and some people will certainly disagree, is to try to do it only with pure c/c++ features, not with all kinds of libraries (boost, etc etc ). It helps separate the language learning from everything else and, AFTER you learn to do it in the pure language variant, you will have a better experience in identifying the pros and cons of each library feature and will choose them wisely. Again, my very own personal opinion is (and I am allowed to have one, dear internet :) ) that using only language features is beneficial for learning and libraries are for productivity.

Have fun!


Have fun!
Yeha sure >.>

I will try to remember you tips :3 and make some more rules for myself.

while am here I may aswell ask
I literately copy pasted my Entityfactory code to do something like factory handler, but instead of returning a smart pointer towards a Entity its points (well suppose to) points towards a "component" instead, than Its suppose to insert the component pointer inside the entity componentlist map, Isnt this suppose to be working or did I missunderstood horrible wrong?

std::shared_ptr<BaseComponent> pComponent;

pComponent = cFactory.ComponentInstantiate<TransformComponent>();
vEntity[0]->AddComponent(pComponent);

class FactoryComponent
{
public:
FactoryComponent(){}
virtual ~FactoryComponent(){}

template<class ComponentType>
std::shared_ptr<ComponentType> ComponentInstantiate()
{
return std::make_shared<ComponentType>();
}
};

class Entity
{
public:
Entity(){};

std::map<std::string,std::shared_ptr<BaseComponent>> ComponentList;

void AddComponent(std::shared_ptr<BaseComponent> type)
{
if(ComponentList.count(type->getTypeName()) == 0)
{
ComponentList.insert(std::make_pair(type->getTypeName(),type));
}
}

void Destroy();



};

The code tags have been messing up. Here's a repost of your code, for others:


std::shared_ptr<BaseComponent> pComponent;
 
pComponent = cFactory.ComponentInstantiate<TransformComponent>();
vEntity[0]->AddComponent(pComponent);

class FactoryComponent
{
public:
	FactoryComponent(){}
	virtual ~FactoryComponent(){}
	
	template<class ComponentType>
	std::shared_ptr<ComponentType> ComponentInstantiate()
	{
		return std::make_shared<ComponentType>();
	}
};

class Entity
{
	public:
	Entity(){};
	
	std::map<std::string,std::shared_ptr<BaseComponent>> ComponentList;
	
	void AddComponent(std::shared_ptr<BaseComponent> type)
	{
		if(ComponentList.count(type->getTypeName()) == 0)
		{
			ComponentList.insert(std::make_pair(type->getTypeName(),type));
		}
	}
	
	void Destroy();
};



I'm not immediately seeing anything wrong. Is it failing to compile?

Yeha It fail to compile :(

here the error code, it says the type cast is possible but not accessible? is that even possible? tbh am really confuse >.<


c:\program files (x86)\microsoft visual studio 10.0\vc\include\memory(1238): error C2243: 'type cast' : conversion from 'TransformComponent *' to 'BaseComponent *' exists, but is inaccessible
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\memory(1536) : see reference to function template instantiation 'std::tr1::_Ptr_base<_Ty>::_Ptr_base<TransformComponent>(std::tr1::_Ptr_base<TransformComponent> &&)' being compiled
1>          with
1>          [
1>              _Ty=BaseComponent
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\memory(1565) : see reference to function template instantiation 'std::tr1::shared_ptr<_Ty>::shared_ptr<TransformComponent>(std::tr1::shared_ptr<TransformComponent> &&,void **)' being compiled
1>          with
1>          [
1>              _Ty=BaseComponent
1>          ]
1>          c:\users\conny.conny-dator\desktop\fusionempty\fusionempty\windowshandler.cpp(99) : see reference to function template instantiation 'std::tr1::shared_ptr<_Ty> &std::tr1::shared_ptr<_Ty>::operator =<TransformComponent>(std::tr1::shared_ptr<TransformComponent> &&)' being compiled
1>          with
1>          [
1>              _Ty=BaseComponent
1>          ]

Oh Forgot to include the component classes

Posting a new post, seeing how I fail misserbly when I try to edit


class BaseComponent
{
	
public:	
	virtual bool Initializing();	
	virtual void Update();
	virtual void Destroy();
	virtual std::string getTypeName();
};

	

class TransformComponent : BaseComponent
{
private:
	struct Transfromers
	{
		XMMATRIX Translation;
		XMMATRIX LocalPosition;
		XMMATRIX WorldPosition;
		XMMATRIX Rotation;
		XMMATRIX Scale;
	
	};


public:

	TransformComponent()
	{

		typeName = "TransfromComponent";
	}
	bool Initializing();
	bool Setting();
	void Update();
	void Destroy();
	std::string getTypeName();
	Transfromers Transform;
	std::string typeName; 
};
I never encountered that error before! happy.png

Googling brought up this on the third hit. The first answer in that thread explains the error message.

Your code:
class TransformComponent : BaseComponent

...has 'TransformComponent' inherit 'BaseComponent', but didn't specify whether to inherit it publicly or privately. Private is default.

So 'TransformComponent' privately inherits 'BaseComponent', and since it privately inherits it, you can't convert the pointers.

The fix is to publicly inherit it:
class TransformComponent : public BaseComponent

"facepalm" forgot I need to inherit the public functions >.<

C# I MISS YOU!

It works!

But dont worry I shall be back with more noobish misstake!

I think you misunderstand the meaning of "public" when inheriting. It doesn't mean "inherit the public functions" it means "keep things public that are public in the base class" or "don't additionally limit visibility of inherited members".

One annoying thing about private inheritance is that your classes will seem "unrelated" to the outside.


class BaseException {};

class DerivedException : BaseException {}; //or private BaseException

try {}
catch (const BaseException& ) {}

You'd expect that when a DerivedException is thrown, it will be caught as well, but since "officially" DerivedException is _not_ a BaseException, it will just slip right through. Unlike in your situation, you will not be getting a compiler error either.

The same applies to overloaded functions, though it's unlikely you will ever create a situation where it won't just fail to compile.

f@dzhttp://festini.device-zero.de

oh that's good to know about the public inheritance.

While am here >.< How do I know if my "compiler" is of c++11?

seeing how the foreach (well I think its foreach) that the servant of the lord showed as a example doesn't work am guessing Visual studio 2010 express is not c++11?

P.S Edit

How do I access a function(or a variable) inside a class that is inside a map that is inside a vector?

I thougth I could do it like this

Test = vEntity[0]->ComponentList[0]->getTypeName();

But I get nothing in return o.o

when I say nothing it just returned " ", what it suppose to return is TransformComponent, And I checked the value before inserting it into the component list with the debug watcher, its does indeed have "TransformComponent" :( but how come I cant access it?
Did I fail with my polymorph again?


std::string Test;
std::vector<std::shared_ptr<Entity>> vEntity;


	vEntity.push_back(eFactory.EntityInstantiate<Entity>());
	vEntity[0]->AddComponent(cFactory.ComponentInstantiate<TransformComponent>());
	if(vEntity[0]->ComponentList.count("TransformComponent") == 1)
	{
		MessageBox(0,"It Works","Yay",MB_OK);
	}
	Test = vEntity[0]->ComponentList[0]->getTypeName();




class TransformComponent : public BaseComponent
{
private:
	struct Transfromers
	{
		XMMATRIX Translation;
		XMMATRIX LocalPosition;
		XMMATRIX WorldPosition;
		XMMATRIX Rotation;
		XMMATRIX Scale;
	
	};


public:

	TransformComponent()
	{
		typeName = "TransfromComponent";
	}
	bool Initializing();
	bool Setting();
	void Update();
	//void Destroy();
	std::string getTypeName();
	Transfromers Transform;
	std::string typeName; 
};


This topic is closed to new replies.

Advertisement