Advertisement

Reduce code dependency with autoptrs

Started by August 07, 2000 03:08 AM
4 comments, last by Void 24 years, 4 months ago
Hi, I have this situation I can''t seem to solve.. There are 3 classes A,B and C B has a member variable of type A, say a. C has a member variable of type B, say b Now if I allocate the a in class B as a stack based object, then class C (and all other def of class C) will need to include the header definition of class A ie dependant of class A To avoid that, a and b has to be allocated on the heap using forward declaration, like so
    

// In class B.h

//---------------

class A;	// forward dec


class B
{
	..
	A	*a;	// pointer dec

};

// In class B.cpp

//---------------


#include "A.h"		// only need to include "A.h" here


//----------------------------------------------------


// In class C.h

//--------------

class B;	// forware dec


class C
{
	..
	B	*b;
};

// In class C.cpp

//-----------------


#include "B.h"		// no need to include A.h at all


[/source]

However, the above code is not exception safe cause if an exception is thrown in the constructor of C, b will not get deallocated.

So I guess a and b should be declared using std::auto_ptr, but how does that work?? I can''t seem to get the thing to compile. If I declare a as
[source]
std::auto_ptr<A> a;		// how to allocate this


std::autoptr<A> a(new A());	// can''t even get this to compile

    
What am I missing?
Do you mean if you throw an exception or the compiler does ?

If you mean, you want to throw an exception, then obviously just delete b and a just before you throw it.


If you mean the compiler is throwing an error, it means you code is too dangerous ! Whatever you''re doing that''s so risky should be done as a separate function after the object is created. eg

    c = new C;try{    c->DoSomethingDangerous();}catch(...){  delete c; // if you want to delete everything... // your exception code in here}[/source][ tangent ]Personally I think by using exceptions and other error handling code, it''s very easy to try to make you code overly complicated and quite dangerous to use.It can be a lot easier to get everything to work if you keep everything as simple as possible, and make sure that each function is either guaranteed to work, or return a normal error that you can anticipate. eg[source]c = new C;  if ( c->DoSomethingDangerous() != OK )  {     printf( "Error initialising object c" );     delete c; // if you want to delete everything...  }    



[ /tangent ]



Game production:
Good, quick, cheap: Choose two.
Game production:Good, quick, cheap: Choose two.
Advertisement
quote: Original post by Danack
Personally I think by using exceptions and other error handling code, it's very easy to try to make you code overly complicated and quite dangerous to use.


Not really. I throw an exception (of my defined type derived from a base exception class) when an error occurs so I removed the need for testing for function call..

Also if I use auto_ptr on object C like

    auto_ptr<C>  c(new C());[/SOURCE]Then there is no need for many try/catchs, new/delete statements (except one try/catch statement in main). The whole code snippent you shown could be accomplished like so[SOURCE]void Function()  // just a function, no try/catch{  auto_ptr<C>  c(new C());    c->DoSomething();   // DoSomething will throw an exception if error}    


The idea I'm trying to achieve is to restrict new/delete totally to the auto_ptrs to make new/delete stack based so it will be deallocated no matter what happens. (exception or not).

Perhaps my question should be how to use auto_ptrs as a class member variable. Does any STL experts knows, plz???


Edited by - Void on August 7, 2000 11:10:02 PM

Edited by - Void on August 7, 2000 11:10:57 PM

Edited by - Void on August 7, 2000 11:12:41 PM
hmm.. something seems to be wrong with the messageboard.. the code is all screwed up..
For the auto_ptr to work, it needs to know about the class fully (i.e. its header file) so that it can call the dtor correctly.

For this kind of thing, you could have a base class for B that has nothing but a virtual dtor, then you can store one of these in the auto_ptr and assign a ''new B'' to it. You''ll also want a function to return a pointer (or reference) to the real type. You only need a forward declaration for a return value, so you''ll have something like.

    class B;class C{	..		std::auto_ptr<B_Base>	*b;	B& GetB();	const B& GetB() const;};    


Inside the GetB function you just cast the auto_ptr to a B, e.g.

B& GetB()
{
return static_cast(*b);
}

Then to access ''b'' you use "GetB().DoSomthing()"

quote:
If you mean the compiler is throwing an error, it means you code is too dangerous !


new throws an exception, so does that mean you shouldn''t use new?
quote: Original post by Wilka
new throws an exception, so does that mean you shouldn''t use new?


What I meant was to restrict the new/delete strictly to autoptrs, so the memory that new points to will always get freed when the object goes out of scope (ie through normal termination or exception)

Thanks.. I will try your method out..

This topic is closed to new replies.

Advertisement