This is supposed to be very basic.
Layout:
class handler {
public:
handler(Connection *conn) { connection = conn; }
virtual void handle() = 0;
};
class http_status : public handler {
public:
http_status(Connection *conn) : handler(conn) { }
void handle();
};
class http_photoserver : public handler {
public:
http_photoserver(Connection *conn) : handler(conn) { }
void handle();
};
Code:
void pick_and_handle() {
if (connection->http_header.uri_str != "/") {
http_photoserver handler(connection);
} else {
http_status handler(connection);
}
handler.handle();
}
This gives an error:
../handler.cpp:51:10: error: expected unqualified-id before ‘.’ token
I'm guessing because compiler doesn't know what handler is cause object is created inside an if statement. I need to pick a handler based on a condition, how do I do that?
Obviously this code works:
if (connection->http_header.uri_str != "/") {
http_photoserver handler(connection);
handler.handle();
} else {
http_status handler(connection);
handler.handle();
}
But doesn't look very sexy! Is it really the only way in c++?
Use a pointer so you get polymorphic behavior:
Declare a pointer somewhere above that code, and then assign an object later in the if statement. Since they are inherited from the same class, OO teaches us that a child can replace a parent :) .
After that it should work.
Just don't forget to destruct! :)
Hope I helped.
The object
handler
doesn't exist outside the scope in which its defined.One solution could be runtime polymorphism, that is, define a base class and a virtual function in it, as:
Then use it as:
Of course it's not the only way. But you may have to use pointers:
(Instead of
unique_ptr
, you can useboost::scoped_ptr
,shared_ptr
, andauto_ptr
also. But in this case,unique_ptr
andboost::scoped_ptr
are most appropriate.)If you go with the pointer approach like the others suggest you should also add a virtual destructor the base class.
This approach can be better expressed using a factory method. Just add a static function in your base class that accepts a
connection
and returns a (smart) pointer to ahandler
. Put the "pick" logic there.If you don't want the pointer approach then the second version you posted is the one to use.
C++ can only do polymorphism in pointers and references. Note that with your code, the actual type of
handler
is not known till runtime. The only thing known is that it will be of one of the subtypes ofhandler
, so you have to declare a pointer to use the polymorphism:I use
std::auto_ptr
to assure the pointer will be automatically deleted when the function ends.