Jump to content

  • Log In with Google      Sign In   
  • Create Account


Red Ant

Member Since 14 Feb 2001
Offline Last Active Jun 17 2014 09:26 AM
-----

#4922557 What's wrong with OOP?

Posted by Red Ant on 16 March 2012 - 06:06 AM

Among those are Paul Graham's and he series of articles on this site: http://www.geocities...izer/oopbad.htm (I haven't read all, since I don't have much time).


Maybe instead of writing an article about why OOP kills baby seals, the guy should have read an article about web page design.

Anyway, common sense says that a programmer who rejects OOP on principle is just as silly as one who won't consider using anything but OOP. There are problems that quite obviously benefit from the use of OOP while there are others that just as obviously benefit from the use of other paradigms. One doesn't have to waft through a dozen pages of diatribe to understand that.


#4922223 Templating safe copy of classes, pointers & arrays

Posted by Red Ant on 15 March 2012 - 04:56 AM

On top of what's been said above, your copy constructor doesn't really "initialize" per se; it assigns. Instead of this

UsesA( const UsesA& other ) { mya = other.mya; }

what you really want to do is this

UsesA( const UsesA& other ) : mya( other.mya ) {}

When writing constructors, it's generally advisable to prefer initialization lists over assignment.


#4920629 C++ Void* Questions

Posted by Red Ant on 09 March 2012 - 05:02 AM

I'm sorry that that's the way you'll have to define a template class, but take it up with those pricks on the c++ standards board who decided to make the export keyword a blank reserved keyword than to have to do any work whatsoever on their compilers to keep themselves compliant.


Well, if you want to keep the implementation separate from the interface you could still do it like this:

// in MenuButton.h
#ifndef MenuButton_h
#define MenuButton_h

class MenuItemBase
{
public:
	virtual void MyFunc(int&) = 0;
};

template <typename T> class MenuButton : public MenuItemBase
{
public:
	virtual void MyFunc( int& x );
};

#include "MenuButton.hpp"

#endif


// in MenuButton.hpp
template <typename T> void MenuButton<T>::MyFunc(int& x)
{
  x = 5;
}



#4894653 [C++] Member initialization

Posted by Red Ant on 16 December 2011 - 05:56 PM

It's also the only way to initialize const members and reference members.


#4877826 Getting the rid of managers

Posted by Red Ant on 28 October 2011 - 03:26 AM

When I read the title of this thread a jolt of enthusiastic excitement went through me ... until I realized that you're talking about a programming issue.


#4871383 Is it still easy to crack .NET and java code nowadays?

Posted by Red Ant on 11 October 2011 - 03:30 AM

I totally disagree with these claims. Did you look at the general code quality for projects on sites like github, sourceforge and co ? 99% of the code available there would not even pass basic code review in any serious software company.


Meanwhile those of us working in one of those "serious" software companies know that that's nothing but wishful thinking. <_<


#4801245 Partial Thread Synchronisation

Posted by Red Ant on 21 April 2011 - 08:53 AM

Ok, I do believe I have fixed it all. Critical sections were't working for me, but mutexes worked like a charm. Problem resolved!


Beware that compared to CRITICAL_SECTIONS, mutexes (or what Windows calls mutexes anyway) are relatively heavy-weight. At any rate, there is no reason why critical sections shouldn't "work for you". Can you elaborate on what kind of problems you've run in with them?


#4800022 std::map and std::string incompatibility?

Posted by Red Ant on 18 April 2011 - 01:11 PM

At least not intentionally, here is the code: [...]

Anything obviously wrong with this?


Nothing do with your problem (which I see you've already solved), but your constructor should at the very least initialize m_lpDevice to a null pointer and not just leave it pointing at some random address. What would be even better is if you could ditch your Init() method and pass lpDevice in the constructor ... that's what constructors are for after all.
Also, that m_MapTextures.clear(); call in your destructor is pointless. This happens implicitly when the map is destroyed.

Next:

map<string, LPDIRECT3DTEXTURE9>::iterator result;
result = m_MapTextures.find(str);

Why not just

const map<string, LPDIRECT3DTEXTURE9>::iterator result = m_MapTextures.find(str);

?

When ever possible, you should make declarations double over as initializations. That way you can often make variables const (as in the example above since you didn't have to change result after initializing it), which helps readability and makes it easier to reason about existing code (for instance when one of your colleages has to understand code that you wrote).

Next issue, D3DXGetImageInfoFromFile() and D3DXCreateTextureFromFileEx Function() both have return values, and the reason they do so is not so you can be a lazy coder and just ignore them. Both of these functions can fail and the way to check for that is to inspect their return values. You should never just assume that a function will probably work if the documentation says that it can fail. Check the return value and if it denotes failure, do something about it ... throw an exception, bring up a message box or at least write an error message to a log file.

EDIT: How did I forget my favorite issue?? :lol:

You should make your class uncopyable by declaring a private copy constructor and a private copy assignment operator and implementing neither. Because otherwise you'll get the compiler default copy constructor / copy assignment operator, which would just copy your instance bit by bit, and the way your class is implemented, that would result in disaster when your destructor runs.


#4798900 Override of placement new

Posted by Red Ant on 15 April 2011 - 02:08 PM

Why would one want to override placement new? :blink: I mean placement new is supposed to take a chunk of existing memory and use it to constuct an instance of something, right? So what could a reimplemented version do differently?


#4791644 Heap corruption at program exit

Posted by Red Ant on 29 March 2011 - 03:40 AM

It's pretty much impossible to predict where things are getting fouled up in your program without seeing the code, so I can only advise you to

  • Make you sure you have no uninitialized variables (always assign initial values to variables. int a = 0; is better than int a;
  • Sprinkle your code with asserts.
  • Always assume that any function that could conceivably fail, WILL fail. Never ignore a function's return value.
  • Be sure that all your classes either have proper copying semantics (i.e. copy c'tor, copy assigment operator and destructor must do the right thing) or are not copyable in the first place (derive from boost::noncopyable or just declare copy c'tor and copy assigment operator private without implementing them).
  • Always check pointers for null before dereferencing them. Also, when a persistent pointer (i.e. one that your carry around with you throughout your program) no longer points to anything, always set it to null.



#4772201 Another Release-Mode crash

Posted by Red Ant on 09 February 2011 - 08:43 PM

Most likely you've corrupted your heap or stack through double deletion, buffer overruns or other fun stuff like that. It's entirely possible that the actual problem is caused in a completely different piece of code than where the crash happens. These kind of bugs are a royal pain in the ass to debug.

I would suggest going through your code and making sure that all your classes either have correct copy semantics, i.e. sport copy constructors, copy assignment operators and destructors that do the right thing __or__ are uncopyable (for instance, by declaring their copy constructors / copy assignment operators as private and not implementing them .... alternatively you could just derive from boost::noncopyable).

Then consider replacing all C-style arrays with std::vector or boost::array and using checked accessors (i.e. at() rather than operator []) to make sure you're not writing / reading past the end of an array.

Also, where appropriate, replace all naked pointers with a shared_ptr implementation, or if you don't want to do this, at least make sure that any pointer that doesn't point to a valid object is null.

Finally, use assert() liberally throughout your code. Really, assert the hell out of everything. I find that this usually helps to find errors as early as possible, rather than letting them go unnoticed and cause weird things to happen later on.


ID3DX11EffectScalarVariable* Scalar;

Don't do that, ever. If you can't assign a proper value on initialization, at least initialize the pointer to null. Yeah, you might be pretty sure that
GetCustomVariable() will assign a value to your pointer ... I can tell you from experience that I've been sure of many things that later turned out to have been wrong. Better play it safe and initialize the pointer to null, then assert( Scalar ) before first access.


#4767690 Qt and opengl

Posted by Red Ant on 31 January 2011 - 04:24 PM

If you are indeed working with Ogre, do __NOT__ use QGLWidget!! Ogre supports both DX and OpenGL, so why would you want ditch that ability for no reason. I'll post the code for a custom Qt/Ogre-widget from one of my projects. I initially took this code from some dude on the Ogre forums (http://ogre3d.org/fo...php?f=2&t=61722).


Anywhere here it is:

The header file
#ifndef Flaps_QtOgreWidget_h
#define Flaps_QtOgreWidget_h

#include <QtGui/QWidget>
#include <Ogre/OgreCommon.h>
#include <boost/noncopyable.hpp>

#include "../../../../FlapsCore/String.h"
#include <iosfwd>
#include <cstddef>

// Ogre forward declarations
namespace Ogre
{
	class RenderWindow;
	class Root;
	class SceneManager;
};

namespace Flaps
{
	/// This class provides a custom Qt widget that can be used for Ogre rendering.
	/// Original code taken from user PolyVox (author of the QtOgre Application Framework).
	class QtOgreWidget : public QWidget, private boost::noncopyable
	{
		Q_OBJECT

	public:
		QtOgreWidget( QWidget& parentWidget, std::basic_ostream< FlapsCore::CharacterType >* logStream );

		void performUpdate();

		/// Initializes the Ogre part of the instance.
		void initialize();

	protected:
		virtual ~QtOgreWidget();

		/// Pointer to a log stream (only for use by the main thread).
		std::basic_ostream< FlapsCore::CharacterType >* const m_logStream;

		/// Returns a reference to the scene manager.
		inline Ogre::SceneManager& sceneMgr() { return *m_sceneManager; }

		inline Ogre::RenderWindow& renderWindow() { return *m_ogreRenderWindow; }

	private:
		Ogre::RenderWindow* m_ogreRenderWindow;

		/// Pointer to the scene manager.
		Ogre::SceneManager* m_sceneManager;

		Ogre::Root* m_root;

		/// The window name specified to Ogre::Root::createRenderWindow(). We might need this again later.
		Ogre::String m_windowName;

		/// Reimplemented to do our Ogre rendering.
		virtual void paintEvent( QPaintEvent* evt );

		/// Reimplemented to propagate the changed dimensions to Ogre.
		virtual void resizeEvent( QResizeEvent* evt );

		/// Returns true if the widget has already been properly set up.
		bool isInitialized() const;

		/// Sets up Ogre and returns a pointer to the Ogre::Root instance.
		Ogre::Root* setUpOgre() const;

		/// Renders the Ogre scene.
		void renderScene();

		/// Must be implemented to update the scene, meaning the positions and orientations of all objects in the scene
		/// must be updated.
		virtual void updateScene() = 0;

		/// Must be implemented in the derived class to actually set up the scene.
		virtual void createScene() = 0;

		/// Reimplemented to return a null pointer. Supposedly this is necessary to avoid flickering.
		virtual QPaintEngine* paintEngine() const;

		/// Reimplemented to handle event with type QEvent::WinIdChange (sent when the win id of the widget changes).
		virtual bool event( QEvent* evt );
	};
}

#endif

And the cpp

#include "QtOgreWidget.h"

// Ogre stuff
#include <Ogre/OgreRoot.h>
#include <Ogre/Ogre.h>

// Qt stuff
#include <QPaintEvent>

// utilities
#include <Utils/Assertions.h>
#include <Utils/StringFunctions.h>
#include <Utils/Logging.h>

// standard C++
#include <ostream>
#include <sstream>
#include <cstddef>

namespace usf = Utils::StringFunctions;

Flaps::QtOgreWidget::QtOgreWidget( QWidget& parentWidget, std::basic_ostream< FlapsCore::CharacterType >* logStream ) :
	QWidget( &parentWidget ),
	m_ogreRenderWindow( nullptr ),
	m_sceneManager( nullptr ),
	m_root( nullptr ),
	m_logStream( logStream )
{
	QPalette colourPalette = palette();
	colourPalette.setColor( QPalette::Active, QPalette::WindowText, Qt::black );
	colourPalette.setColor( QPalette::Active, QPalette::Window, Qt::black );
	setPalette( colourPalette );
}

Flaps::QtOgreWidget::~QtOgreWidget()
{
	if ( m_ogreRenderWindow )
	{
		m_ogreRenderWindow->destroy();
	}
}

void Flaps::QtOgreWidget::initialize()
{
	setAttribute( Qt::WA_PaintOnScreen );
	setAttribute( Qt::WA_OpaquePaintEvent );
	setAttribute( Qt::WA_NoSystemBackground );
	setAutoFillBackground( false );

	setFocusPolicy( Qt::StrongFocus );

	m_root = Ogre::Root::getSingletonPtr();
	
	if ( ! m_root )
	{
		m_root = setUpOgre();
		HARD_ASSERT( m_root );
	}

	{
		std::ostringstream out;
		out << "QtOgreWidget_at_0x" << std::hex << static_cast < const void* > ( this );
		m_windowName = out.str();
	}

	// The external windows handle parameters are platform-specific
	const Ogre::String externalWindowHandleParams = Ogre::StringConverter::toString( reinterpret_cast < std::size_t > ( winId() ) );
	Ogre::NameValuePairList params;
	params[ "externalWindowHandle" ] = externalWindowHandleParams;

	m_ogreRenderWindow = m_root->createRenderWindow( m_windowName, width(), height(), false, &params );
	HARD_ASSERT( m_ogreRenderWindow );

	if ( m_logStream )
	{
		NEW_LOG_ENTRY_W( *m_logStream ) << TXT_( "Created render window with name \"" ) << usf::encode< FlapsCore::CharacterType > (  m_windowName ) << TXT_( "\".\n" );
	}
 
	m_sceneManager = m_root->createSceneManager( Ogre::ST_EXTERIOR_CLOSE );
	HARD_ASSERT( m_sceneManager );

	createScene();
}

Ogre::Root* Flaps::QtOgreWidget::setUpOgre() const
{
	/// @todo Do not hard-code these path names! Also allow user to specify a file name to which the Ogre library can spew debug output.
	Ogre::Root* const ogreRoot = new Ogre::Root( "OgrePlugins.cfg", Ogre::String(), Ogre::String() );

	const Ogre::RenderSystemList& renderers = ogreRoot->getAvailableRenderers();
	HARD_ASSERT( ! renderers.empty() );

	if ( m_logStream )
	{
		NEW_LOG_ENTRY_W( *m_logStream ) << TXT_( "List of available render systems contains " ) << renderers.size() << TXT_( " entries.\n" );

		for ( Ogre::RenderSystemList::const_iterator it = renderers.begin(); it != renderers.end(); ++it )
		{
			NEW_LOG_ENTRY_W( *m_logStream ) << TXT_( "Render system \"" ) << usf::encode< FlapsCore::CharacterType > (  ( *it )->getName() ) << TXT_( "\" found in list of available render systems.\n" );
		}
	}
 
	/// @todo Implement something to allow the user to pick a rendering system ... and don't do it all directly in this class.
	Ogre::RenderSystem* const renderSystem = renderers.front();
	HARD_ASSERT( renderSystem );
 
	ogreRoot->setRenderSystem( renderSystem );

	{
		std::ostringstream out;
		out << width() << "x" << height();
		renderSystem->setConfigOption( "Video Mode", out.str() );
	}
 
	// initialize without creating window
	ogreRoot->getRenderSystem()->setConfigOption( "Full Screen", "No" );
	ogreRoot->saveConfig();
	ogreRoot->initialise( false );

	return ogreRoot;
}

bool Flaps::QtOgreWidget::isInitialized() const
{
	return m_ogreRenderWindow;
}

void Flaps::QtOgreWidget::paintEvent( QPaintEvent* evt )
{
	if ( ! isInitialized() )
	{
		return;
	}

	renderScene();

	evt->accept();
}

void Flaps::QtOgreWidget::renderScene()
{
	m_root->_fireFrameStarted();
	m_ogreRenderWindow->update();
	m_root->_fireFrameRenderingQueued();
	m_root->_fireFrameEnded();
}

void Flaps::QtOgreWidget::performUpdate()
{
	updateScene();

	/// @todo Is it really necessary to render directly or should we be causing a QPaintEvent to be sent to this widget?
	renderScene();
}

void Flaps::QtOgreWidget::resizeEvent( QResizeEvent* )
{
	m_ogreRenderWindow->windowMovedOrResized();
}

QPaintEngine* Flaps::QtOgreWidget::paintEngine() const
{
	return nullptr;
}

 bool Flaps::QtOgreWidget::event( QEvent* evt )
 {
	 /// @todo How do we react to this PROPERLY!?
	 // Hmm, apparently this event is sent to the widget on creation.
	 //HARD_ASSERT( evt->type() != QEvent::WinIdChange ); 
	 return QObject::event( evt );
 }

This code is directly from my project .... I didn't strip out all the project-specific things, so just throw away the stuff you don't need.


PARTNERS