这应该是非常基本的。
布局:
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 ++的唯一方法吗?
答案 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_ptr
,shared_ptr
和auto_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
的(智能)指针。把“挑选”逻辑放在那里。
如果您不希望指针逼近,那么您发布的第二个版本就是要使用的版本。