How to use doxygen to generate caller and inheritance diagram.

Share Button

Since I’m a newbie programmer and code in our team is really complicated, I always found myself lost somewhere in the code sea. Luckily our code is doxygenized long times ago, so  I want to try out some cool features of doxygen. The most important feature to me is inheritance diagram and the usage relations between classes. (something like class A has a member of class B) So here is how to do it:

  1. Install graphviz which has a tool called dot that doxygen use to draw those diagrams:
  2. Set HAVE_DOT, CALL_GRAPHCALLER_GRAPH, and EXTRACT_ALL to YES.
  3. Set DOT_GRAPH_MAX_NODES and MAX_DOT_GRAPH_DEPTH to some big number.
  4. Generate doxygen files.
  5. Done. Then you will see diagrams as this.

Here we assume your files are already doxygenized. If you don’t know what doxygen is or how to use doxygen, you may refer to the reference link to find out.

References:
Doxygen
Doxygen manual

Effective C++ item 13: Use objects to manage resources.

Share Button

Always use object to manage resources! If you delete a pointer or release a handler manually by yourself, there is a great chance you will make mistake or forget something.

There are two critical aspects of using objects to manage resources:

  1. Resources are acquired and immediately turned over to resource-managing objects. The idea of using objects to manage resources is often called Resource Acquisition Is Initialization (RAII).
  2. Resource-managing objects use their destructors to ensure that resources are released.

You can use std::auto_ptrs or std::tr1::shared_ptr to manage heap memory.

There are several points you should keep in mind when you using those two smart pointers:

  1. std::auto_ptr assumes sole ownership which means copying one to another will set the previous one to null!
  2. STL containers require that their contents exhibit “normal” copying behavior, so containers of std::auto_ptr aren’t allowed.
  3. Both std::auto_ptr and std::tr1::shared_ptr use delete in their destructors, not delete[ ]. That means that using them with dynamically allocated arrays is a bad idea, though, regrettably, one that will compile.

Reference:
“Effective C++” Third Edition by Scott Meyers.

Effective C++ item 12: Copy all parts of an object.

Share Button

This one is simple. Don’t forget to copy all parts of an object in copy constructor or assignment operator!

There are two cases you tend to make mistakes.

  1. Make sure you modify copy constructor and assignment operator, if you add a member to a class.
  2. Make sure you call the copy constructor and assignment operator of base class in derived classes.

Reference:
“Effective C++” Third Edition by Scott Meyers.

Effective C++ item 11: Handle assignment to self in operator=.

Share Button

You can easily assign an object to itself without knowing it.

It is dangerous to assign an object to itself if your class doesn’t handle this kind of operator  appropriately. Let’s consider an example here:

You will be dead if you assign a Widget object to itself cause you will end up with holding a pointer to a deleted object!

One way, but not best way to deal with self assignment is to write code to explicitly deal with this situation:

This is not the best way to solve the problem cause this operator is not exception-safe. What does this mean? Imagine what if an exception is thrown when

is been executed (for example, not enough memory), then the object will hold a pointer to a deleted Bitmap.

Luckily, making operator= exception-save typically renders it self-assignment-safe, too. So  the best way to accomplish that is:

Now if “new Bitmap” throws an exception, pb remains unchanged. Even without the identity test, this code handles assignment to self, because we make a copy of the original bitmap, point to the copy we made, and then delete the original bitmap.

 

Reference:
“Effective C++” Third Edition by Scott Meyers.

Effective C++ item 10: Have assignment operators return a reference to *this.

Share Button

If you want to concatenate assignments like:

The convention is to make the assignment operator return a reference of *this. And then this  applies to all assignment operators something like +=, -=, etc.. It’s just an convention to follow, but there is no reason to not follow it:

And I’ll talk about handle self assignment in next post.

Reference:
“Effective C++” Third Edition by Scott Meyers.

Effective C++ item 9: Never call virtual functions during construction or destruction.

Share Button

Don’t call virtual functions during construction or destruction, because such calls will never go to a more derived class than that of the currently executing constructor or destructor. In other words, it will call the version of base class rather than that of derived class. For example if you has a Transaction base class which keeps the log of buy and sell transactions. Probably you will write code like this:

In the code above, the logTransaction() method in the constructor of Transaction base class will always call Transaction::logTransaction() rather than BuyTransaction::logTransaction() or SellTransaction::logTransaction(), this is because the object is as if it were of the base type during base class construction. In the example  above, since the logTransaction() is pure virtual in the base class you will probably get a warning or error from compiler. If logTransaction() is just a virtual function, then you are highly possible to debug to hell to find out why your derived methods are never called.

Reference:
“Effective C++” Third Edition by Scott Meyers.