18 Nov 2006 | programming |
edit
When do you need to declare a destructor virtual?
Recently I’ve been involved in a thread on qt-interest mailing list about virtual destructors. A few people there suggested that you should always make the destructor of your class virtual. I strongly disagree.
The argument was that if you use the virtual keyword on your destructor you will always be on the safe side. If someone inherits from your class and then deletes one of his instances of the class by a pointer to your base class you are sure his destructor gets called. So you are designing a class with value semantics (can be copied, can be assigned to) and you fear that someone will eventually inherit from your class so you make the destructor virtual. Well then why not make all the methods virtual so that if someone will inherit your class will have the possibility to customize its behavior. Is this starting to sound wrong? Well it should.
Just to be clear, I’m not trying to say that declaring a destructor virtual on a class WILL cause trouble. I’ll try to explain why it’s BAD CODING STYLE to always declare you destructor virtual. A good coding style will most probably keep you away from dangers like inheriting a class that has not been meant to be used as a base class.
As Herb Sutter and Andrei Alexandrescu state in “C++ Coding Standards: 101 Rules, Guidelines, and Best Practices” item 32:
Be clear what kind of class you're writing
Be clear to yourself and to the users of your class. The most used types of classes are value classes and polymorphic classes. As a rule of thumb:
Never try to write a class that is of both types.
These types of classes are complementary. Value types are concrete types that mimic the built-in types, which are usually instantiated on the stack and are passed around by reference or by value. Polymorphic classes are meant to be used as base classes, are usually instantiated on the heap and used via (smart) pointer. In C++ the keyword virtual means “this will be a polymorphic class” and a copy constructor and assignment operator mean “this will be a value class”.
Now when the destructor should be declared virtual?
You MUST declare the destructor virtual ONLY if you are creating a polymorphic class witch has a PUBLIC destructor. That’s it. That’s the only case when you must declare the destructor virtual. If you don’t declare it virtual BAD THINGS will happen (destructors of child classes will not be called when deleting by base class).
1 struct A {
2 ~A(){
3 cout << " calling ~A()";
4 }
5 };
6
7 struct B: public A {
8 ~B(){
9 cout << "~B()";
10 }
11 };
12
13 int main(){
14 A* a = new B;
15 delete a; ///In this case ~B() will not be called.
16 }
You SHULD (read MUST) NOT declare your destructor virtual in any other case. If you declare it virtual the biggest problem is someone using your class might think that your class is a polymorphic class that can be inherited from. If this happens the code will probably work but will be awkward and difficult to write and maintain. There is also a performance hit that comes with virtual destructors but unless you are writing something where every nanosecond counts you will not care about this hit.
Now what do you do if you find a nice class that is a value class (even if the author made the destructor virtual) but you want to add some custom functionality to it?
Use FREE FUNCTIONS. That’s it. Having free functions will not make your coding less Object Oriented. Free function will give you the same access level as inheriting from a value class as value classes don’t usually have protected methods. To avoid problems place the free functions in the same namespace as the class. As an example if you have a string class and want to have a method that will return the word count from the string:
1 int wordCount( const string& str ){
2 ///count the words
3 return count;
4 }
5
6 void doSomething(const string& str){
7 /// instead of str.wordCount() you will now have:
8 int count = wordCount(str);
9 }
There are lots of things to be said about class design. You should search for books written on the subject and learn about good ways of creating classes. The sad part is that until you are bitten by a bad design that you have to live with you most probably will not understand the importance of good design and coding style in general.
In the end if you are an employer and want to quickly see if a candidate knows about virtual functions ask him what “static virtual functions” and “virtual constructors” have in common. (if you don’t know the answer contact me).
Updates
A very good article about virtuality.
And another great article about virtual functions.
"Virtual functions should be treated very much like data members — make them private, until design needs indicate a less restricted approach is indicated. It is much easier to promote them to a more accessible level, than it is to demote them to a more private level."
08 Nov 2006 | qt-boost |
edit
Problem
Creating a wrapper over QHttp that can perform GET and POST requests in a synchronous way.
Solution
In Qt4 QHttp can perform HTTP requests, but the API only allows asynchronous requests. This means that you need to specify a set of slots to handle the signals that can be emitted while the request if performed. Now don't get me wrong, this is event driven programming and most of the times is the right way to go especially when writing a Qt based application. The cases when event driven operations prove difficult to use are rare and usually can be programmed using events.
Recently I’ve developed a small application that had to do a number of requests in a specified order and show a message if an error was to occur. The algorithm was simple:
1 foreach ( Request r , requestList )
2 if(! runRequest(r) ) return error;
For writing something like this I would like to not split the algorithm across a set of slots. So I would like to have a possibility to run a request and wait for it to finish.
Implementation
We start by creating a SyncHTTP class that is derived from QHttp:
1 class SyncHTTP: public QHttp{
2 Q_OBJECT
3 /// id of current request
4 int requestID;
5 /// error status of current request
6 bool status;
7 /// event loop used to block until request finished
8 QEventLoop loop;
9
10 public:
11 /// structors
12 SyncHTTP( QObject * parent = 0 )
13 :QHttp(parent),requestID(-1),status(false){}
14
15 SyncHTTP( const QString & hostName,quint16 port = 80, QObject * parent = 0 )
16 :QHttp(hostName,port,parent),requestID(-1),status(false){}
17
18 virtual ~SyncHTTP(){}
19 }
Now we need to implement the methods for syncGet and syncPost to mimic the get and post methods from QHttp:
1 /// send GET request and wait until finished
2 bool syncGet ( const QString & path, QIODevice * to = 0 )
3 {
4 ///connect the requestFinished signal to our finished slot
5 connect(this,SIGNAL(requestFinished(int,bool)),
6 SLOT(finished(int,bool)));
7 /// start the request and store the requestID
8 requestID = get(path, to );
9 /// block until the request is finished
10 loop.exec();
11 /// return the request status
12 return status;
13 }
14 /// send POST request and wait until finished
15 bool syncPost ( const QString & path, QIODevice * data, QIODevice * to = 0 )
16 {
17 ///connect the requestFinished signal to our finished slot
18 connect(this,SIGNAL(requestFinished(int,bool)),
19 SLOT(finished(int,bool)));
20 /// start the request and store the requestID
21 requestID = post(path, data , to );
22 /// block until the request is finished
23 loop.exec();
24 /// return the request status
25 return status;
26 }
27
28 bool syncPost ( const QString & path, const QByteArray& data, QIODevice * to = 0 )
29 {
30 /// create io device from QByteArray
31 QBuffer buffer;
32 buffer.setData(data);
33 return syncPost(path,&buffer,to);
34 }
The syncGet and syncPost functions both use the same strategy. They connect the requestFinished signal from QHttp to a finished slot, they ask the QHttp object to perform the request. The QHttp's get/post method returns immediately with the request id that has been assigned to the current request. Now the nice part: After asking the QHttp object to perform the request we need to wait for it to finish, so we create an event loop and start it. The main event loop is now blocked and we are nor risking being called aging while executing the request. The blocking code is not using tricks like sleep or infinite loops so we don't end up using 100% CPU or wasting time sleeping. Now we just need to implement the finished slot to save the result and exit the loop:
1 protected slots:
2 virtual void finished(int idx, bool err)
3 {
4 /// check to see if it's the request we made
5 if(idx!=requestID) return;
6 /// set status of the request
7 status = !err;
8 /// end the loop
9 loop.exit();
10 }
Now this slot first checks to see if it's being called for our request and returns if not, after that saves the error status returned by the QHttp object and exits the loop. The execution now will return in the syncGet/syncPost function that will return the status to the caller.
Testing
Ok, let's write a small test application. Writing real automated test cases for this kind of class is possible but not trivial so will just write a small test app.
1 #include
2 #include
3 #include "synchttp.h"
4
5 int main(int argc, char *argv[])
6 {
7 QApplication a(argc,argv);
8 /// create object
9 SyncHTTP h("www.google.com");
10
11 ///prepare output buffer
12 QBuffer getOutput;
13 h.syncGet( "/search?q=erata.net",&getOutput );
14 qDebug() << getOutput.data();
15
16 QByteArray data(QString("q=data").toLatin1());
17 QBuffer postOutput;
18
19 h.syncPost( "/search",data, &postOutput);
20
21 qDebug() << postOutput.data();
22
23 return 0;
24 }
Now in conclusion i would like to say that i recommend using this class only when you simply need to perform a request and know if it was successful or not. On any other case, where you need to do more complicated things learn to use Qt's event driven programming model.
Download synchttp.h
PS: this is my first programming HOWTO so be merciful :)
The code and ideas from this article can be used without any license restrictions. You can consider it under BSD,MIT,BSL or whatever suites you best. Providing my name or a link to this website would be nice but is not required.
25 Oct 2006 | projects |
edit
This is not really a project, just my opinion on how modern websites should be done.
Doing Erata.NET website I've learned the advantages of using strict XHTML ( 1.1 ) and CSS. Web design is getting closer to programing this way. You have a modular structure, an easy to follow document layout on witch you can apply styles with CSS. I'm not much of a designer and I'm happy with this style of web design because it allows me to create the structure of the website and use the style-sheets that a real designer can provide.
This site was mostly tested using firefox, but should look the same in any standards compliant browser. From what I've seen in Internet Explorer there are a few thing that don't look exactly the same, but i consider it a waste of time to try to fight browser stupidity. As long as you are using a bad browser you will be able to use this website, just don't complain if some things don't look that good.
This is it for now, until I'll find the time and resources to write an "how to start with XHTML & CSS" but I'd like to recommend to anyone to take the time to understand and learn how this technologies work.