在C语句中创建if语句中的对象时的范围问题

时间:2011-06-13 11:19:06

标签: c++ object scope

这应该是非常基本的。

布局:

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();
};

代码:

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

这会出错:

../handler.cpp:51:10: error: expected unqualified-id before ‘.’ token

我猜是因为编译器不知道什么处理程序是因为在if语句中创建了对象。我需要根据条件选择一个处理程序,我该怎么做?

显然这段代码有效:

  if (connection->http_header.uri_str != "/") {
     http_photoserver handler(connection);
     handler.handle();
  } else {
     http_status handler(connection);
     handler.handle();
  }

但是看起来不太性感!它真的是c ++的唯一方法吗?

6 个答案:

答案 0 :(得分:8)

当然,这不是唯一的方法。但你可能不得不使用指针:

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();
}

(而不是unique_ptr,您也可以使用boost::scoped_ptrshared_ptrauto_ptr。但在这种情况下,unique_ptr和{{1}最合适的。)

答案 1 :(得分:8)

使用指针以获得多态行为:

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

答案 2 :(得分:2)

C ++只能在指针和引用中执行多态操作。请注意,使用您的代码,直到运行时才知道handler的实际类型。唯一已知的是它将是handler的一个子类型,所以你必须声明一个使用多态的指针:

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();
}

我使用std::auto_ptr来确保在函数结束时自动删除指针。

答案 3 :(得分:0)

对象handler不在其定义的范围之外。

一种解决方案可能是运行时多态,即在其中定义基类和虚拟函数,如下所示:

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
};   

然后将其用作:

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

答案 4 :(得分:0)

在该代码上方的某处声明一个指针,然后在if语句中稍后指定一个对象。由于它们是从同一个类继承的,因此OO告诉我们一个孩子可以替换父类:)。

之后它应该有用。

不要忘记毁灭! :)

希望我帮助过。

答案 5 :(得分:0)

如果你像其他人建议的那样使用指针方法,你还应该在基类中添加一个虚拟析构函数。

使用工厂方法可以更好地表达此方法。只需在基类中添加一个静态函数,该函数接受connection并返回指向handler的(智能)指针。把“挑选”逻辑放在那里。

如果您不希望指针逼近,那么您发布的第二个版本就是要使用的版本。