Is it possible to make a class accept value null?

Started by
10 comments, last by johnnyBravo 20 years, 5 months ago
Ive got an Image class for directx that loads textures. and ive got a drawVertex function that requires you enter an image from the image class. But sometimes if you don''t want an image i want it so you can make it equal null. how would i do this? eg

//image class

class Image {
public:
	LPDIRECT3DTEXTURE9 lp_Texture;
	int width;
	int height;
	void init(char filename[], DWORD colourKey);

	~Image()
	{
		if(lp_Texture != NULL )
			lp_Texture->Release();
		
void Image::init(char filename[], DWORD colourKey=0)
{
	lp_Texture=NULL;
	D3DXIMAGE_INFO fileInfo={NULL};
	D3DXGetImageInfoFromFile(filename,&fileInfo);
	width =fileInfo.Width;
	height=fileInfo.Height;
	D3DXIMAGE_INFO d3dxImageInfo;
	D3DXCreateTextureFromFileEx( D3D::lp_Device, filename, fileInfo.Width, fileInfo.Height, 1, D3DPOOL_DEFAULT, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, colourKey, &d3dxImageInfo, NULL, &lp_Texture );
	}

//draw vertex function

static void drawVertice(enum _D3DPRIMITIVETYPE type, int index, int triangles,	Image ℑ )
	{
		lp_Device->SetTexture( 0, image.lp_Texture );
		lp_Device->DrawPrimitive( type, index, triangles );
	}

//running drawvertex, i want to enter NULL for the class instead of an image class, so it knows there is no image to use

D3D::drawVertice(D3DPT_TRIANGLESTRIP,0,1,NULL);
thanks,
Advertisement
Just check if the image pointer is valid. ie: check if it''s not 0, becuase NULL is actually just a define for 0 in C++.

static void drawVertice(enum _D3DPRIMITIVETYPE type, int index, int triangles,	Image *image ){	if( image )		lp_Device->SetTexture( 0, image.lp_Texture );	lp_Device->DrawPrimitive( type, index, triangles );}


:::: [ Triple Buffer ] ::::
[size=2]aliak.net
just use an if statement in drawVertice to check if it''s pointing to NULL. if it is, turn off texturing and draw.
GSACP: GameDev Society Against Crap PostingTo join: Put these lines in your signature and don't post crap!
when i have "Image *image" instead of "Image ℑ i get the error
quote:
error C2228: left of ''.lp_Texture'' must have class/struct/union type


and if i try put null in while ive got "Image ℑ"
i get the error
quote:
error C2664: ''drawVertice'' : cannot convert parameter 4 from ''const int'' to ''class graphic::Image &''
A reference that is not to ''const'' cannot be bound to a non-lvalue


so what to do?
quote:Original post by johnnyBravo
when i have "Image *image" instead of "Image ℑ i get the error
quote:
error C2228: left of ''.lp_Texture'' must have class/struct/union type



use image->lp_Texture

ah thanks,

just a quick question, is there any advantage or disadvantage of using pointers instead of references in functions apart from being able directly edit or whatever the referenced thing? The only reasion i orginally used references was so i didnt have to type "&" infront of every thing.
quote:Original post by johnnyBravo
Ive got an Image class for directx that loads textures.

and ive got a drawVertex function that requires you enter an image from the image class.

But sometimes if you don''t want an image i want it so you can make it equal null.

how would i do this?

You could possibly use the Null Object Idiom in conjunction with function overloading. For example:

#include <iostream>class Image{};class Null{} nil;void foo(int, int, int, const Image&){	std::cout << "foo with Image\n";}void foo(int, int, int, const Null&){	std::cout << "foo with Null\n";}int main(){	foo(1,2,3, Image());	foo(1,2,3, nil);}


Here, you create a globally-scoped entity called "nil" of a type distinct from all others (in this case Null) and you use it for overloading the function. This simulates how languages such as Python and Lisp work, and is arguably more sane than the built-in way in which C++ deals with null (where it has no distinct type of its own).
quote:Original post by SabreMan
You could possibly use the Null Object Idiom in conjunction with function overloading. For example:
&lt;source code&gt;
Here, you create a globally-scoped entity called "nil" of a type distinct from all others (in this case Null) and you use it for overloading the function. This simulates how languages such as Python and Lisp work, and is arguably more sane than the built-in way in which C++ deals with null (where it has no distinct type of its own).

Is there an advantage to this as opposed to overloading the function with one less argument, eg:
class Image{};void foo(int, int, int, const Image&){// draw with image}void foo(int, int, int){// draw without image}int main(){   foo(1,2,3, Image());   foo(1,2,3);}

To the OP:
In fact, in this particular case, I would expect the use of a pointer, with NULL checks within the function would be better, since it would a) let you pass in a null pointer without the caller knowing that it''s null, and b) mean you don''t have to duplicate code between two versions of the function (nb: of course, duplication could be reduced or eliminated even if you choose to overload the function, by breaking it down into separate sub-functions, but depending on what exactly you need to do in the overloaded function, this may result in less readable code).

John B
[gdnick: JohnBSmall, but I''m at school and don''t wish to log in]
quote:Original post by Anonymous Poster
Is there an advantage to this as opposed to overloading the function with one less argument

Maybe, maybe not. It really depends on how the OP wants to call the function, which is not something for me to decide.
quote:
In fact, in this particular case, I would expect the use of a pointer, with NULL checks within the function would be better

A way of extending the Null Object idea might be to derive an hierarchy for Images, where the necessary logic is polymorphic across different types of Image. The hierarchy could then include a NullImage type and the call-site could remain ignorant of the concrete type passed through. There''s actually other problems in the OP''s code that I didn''t comment on, such as lack of encapsulation and cohesiveness. Resolution of these problems would probably result in the use of polymorphic despatch dropping out as the natural solution.
quote:
it would a) let you pass in a null pointer without the caller knowing that it''s null

This really depends on the creation policy for Image types.
quote:
b) mean you don''t have to duplicate code between two versions of the function

This is a two-way argument. If the code is switching on the (conceptual) type of something, then it really contains two different implementations of something. Whether you perceive that as a problem depends on your coding ethics, I suppose. I''ve grown very suspicious of explicit type-switches. The only reason this is not perceived as a type-switch in C++ is because C++ handles nulls in an incredibly stupid way. Its still conceptually a type-switch.
quote:Original post by SabreMan
quote:Original post by me
Is there an advantage to this as opposed to overloading the function with one less argument

Maybe, maybe not. It really depends on how the OP wants to call the function, which is not something for me to decide.

That''s true of course, but ignoring the OP''s specific problem for a moment, is there a situation where using a null parameter instead of no parameter at all would give an advantage (other than simple stylistic preference)?
quote:A way of extending the Null Object idea might be to derive an hierarchy for Images, where the necessary logic is polymorphic across different types of Image. The hierarchy could then include a NullImage type and the call-site could remain ignorant of the concrete type passed through. There''s actually other problems in the OP''s code that I didn''t comment on, such as lack of encapsulation and cohesiveness. Resolution of these problems would probably result in the use of polymorphic despatch dropping out as the natural solution.

Perfectly true. Do you believe that such class hierarchies should be used even if they result in a very simple (but, I suspect, not uncommon) trio of classes?
ie, abstract base class defining interface, single real concrete class implementing interface, and a concrete null class implementing everything (or nearly everything) with empty functions.
quote:
quote:it would a) let you pass in a null pointer without the caller knowing that it''s null

This really depends on the creation policy for Image types.

True of course.
quote:If the code is switching on the (conceptual) type of something, then it really contains two different implementations of something. Whether you perceive that as a problem depends on your coding ethics, I suppose. I''ve grown very suspicious of explicit type-switches. The only reason this is not perceived as a type-switch in C++ is because C++ handles nulls in an incredibly stupid way. Its still conceptually a type-switch.

True. However, it is (again, I suspect - I can''t provide statistics) common to have a situation in which a type-switch is a matter of running through the full code path for one type, but excluding part of that code path for another type (generally, the null type). Do you believe that it is still bad practice if the type-switches consist of having blocks of the function code wrapped up in if statements? And if so, what do you think is the best way of organising the code in this case?
// by breaking the function down?  something like:void foo(int a, int b, const Object* c){   // code block 1   if (c != 0)   {      // code block 2   }   // block 3   if (c != 0)      // block 4 (single statement block)   // block 5}// Should foo be broken up?  Becoming:void foo(int a, int b, const Object& c){   block_1_code();   block_2_code(a, c);   block_3_code(b);   block_4_code(c);   block_5_code();}void foo(int a, int b, const Null& c){   block_1_code();   block_3_code(b);   block_5_code();}// or perhaps an attempt should be made to remove all type// specific code from functions that aren''t members of the// type they''re operating with, so that abstract interfaces// can be used to remove all explicit type checks// eg,void foo(int a, int b, const Object* c){   // code block 1   if (c != 0)   {      c->bar(a);   }   // block 3   if (c != 0)      c->do_some_stuff();   // block 5}// where Object has become an abstract class, and foo() is// given a pointer to an instance of a concrete implementation// of the Object interface

John B
The best thing about the internet is the way people with no experience or qualifications can pretend to be completely superior to other people who have no experience or qualifications.

This topic is closed to new replies.

Advertisement