Scope issue while creating objects inside if state

2019-05-26 22:03发布

问题:

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++?

回答1:

Use a pointer so you get polymorphic behavior:

auto_ptr<handler> theHandler = (connection->http_header.uri_str != "/") ?
    new http_photoserver(connection) :
    new http_status(connection);
theHandler->handle();


回答2:

Of course it's not the only way. But you may have to use pointers:

void pick_and_handle() {
    unique_ptr<handler> http_handler;
    if (connection->http_header.uri_str != "/")
        http_handler.reset(new http_photoserver(connection));
    else
        http_handler.reset(new http_status(connection));
    http_handler->handle();
}

(Instead of unique_ptr, you can use boost::scoped_ptr, shared_ptr, and auto_ptr also. But in this case, unique_ptr and boost::scoped_ptr are most appropriate.)



回答3:

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 of handler, so you have to declare a pointer to use the polymorphism:

void pick_and_handle() {
  std::auto_ptr<handler> h;
  if (connection->http_header.uri_str != "/") {
     h.reset(new http_photoserver(connection));
  } else {
     h.reset(new http_status(connection));
  }
  h->handle();
}

I use std::auto_ptr to assure the pointer will be automatically deleted when the function ends.



回答4:

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:

struct base_handler
{
   virtual void handle(Connection *conn) = 0;   //interface
   virtual ~base_handler() {}  //must make it virtual!
};
struct http_photoserver  : base_handler
{
     virtual void handle(Connection *conn)  {}  //implementation
};
struct http_status : base_handler
{
     virtual void handle(Connection *conn)  {}  //implementation
};   

Then use it as:

base_handler *phander ; 
if (connection->http_header.uri_str != "/") {
     phandler = new http_photoserver(connection);
} else {
     phandler = new http_status (connection);
}
phandler->handle();
//...
delete phandler;


回答5:

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.



回答6:

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 a handler. 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++ object scope