在if语句if C++中创建对象时出现作用域问题

Scope issue while creating objects inside if statement if C++

本文关键字:if 问题 作用域 创建对象 语句 C++      更新时间:2023-10-16

这应该是非常基本的。

布局:

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++中唯一的方法吗?

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

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

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

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

(您也可以使用boost::scoped_ptrshared_ptrauto_ptr来代替unique_ptr。但在这种情况下,unique_ptrboost::scoped_ptr是最合适的。)

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来确保指针在函数结束时会自动删除。

对象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;

在代码上方的某个位置声明一个指针,然后在if语句中稍后分配一个对象。由于它们是从同一个类继承的,OO告诉我们,子代可以取代父代:)。

之后,它应该会起作用。

只是别忘了销毁!:)

希望我能帮上忙。

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

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

如果你不想要指针方法,那么你发布的第二个版本就是你要使用的。