类成员函数在C+;中相互调用的优势是什么+;? 我是C++新手。我发现下面的编程风格对我来说很有趣。我在这里写了一个简化版本 #include <iostream> using namespace std; class MyClass { public : MyClass(int id_) : id(id_) { cout<<"I am a constructor"<<endl; } bool error = false; void run() { //do something ... if (!error) { read(); } } void read() { //do something ... if (!error) { write(); } } void write() { //do something ... if (!error) { read(); } } private : int id; }; int main() { MyClass mc(1); mc.run(); return 0; }
这是我的看法: 关于递归 导致堆栈溢出的一种方法是让函数递归地调用自身,使调用堆栈溢出。一组以循环方式相互调用的函数将等价于此,因此是的,您的直觉是正确的 该算法的迭代版本,如您描述的循环,可以防止这种情况 现在,另一件可以防止堆栈溢出的事情是存在可以针对尾部递归进行优化的代码。尾部递归优化需要一个实现此功能的编译器。大多数主要的编译器都实现了它。您提到的Boost.Asio函数似乎受益于此优化 关于代码设计 <>现在,C++实现了许多编程范例。这些范例也由许多其他编程语言实现。与您正在讨论的内容相关的编程范例如下:类成员函数在C+;中相互调用的优势是什么+;? 我是C++新手。我发现下面的编程风格对我来说很有趣。我在这里写了一个简化版本 #include <iostream> using namespace std; class MyClass { public : MyClass(int id_) : id(id_) { cout<<"I am a constructor"<<endl; } bool error = false; void run() { //do something ... if (!error) { read(); } } void read() { //do something ... if (!error) { write(); } } void write() { //do something ... if (!error) { read(); } } private : int id; }; int main() { MyClass mc(1); mc.run(); return 0; },c++,boost,boost-asio,C++,Boost,Boost Asio,这是我的看法: 关于递归 导致堆栈溢出的一种方法是让函数递归地调用自身,使调用堆栈溢出。一组以循环方式相互调用的函数将等价于此,因此是的,您的直觉是正确的 该算法的迭代版本,如您描述的循环,可以防止这种情况 现在,另一件可以防止堆栈溢出的事情是存在可以针对尾部递归进行优化的代码。尾部递归优化需要一个实现此功能的编译器。大多数主要的编译器都实现了它。您提到的Boost.Asio函数似乎受益于此优化 关于代码设计 现在,C++实现了许多编程范例。这些范例也由许多其他编程语言实现。与您正在讨论的内容相
- 结构化编程
- 面向对象编程
到目前为止,您提供的逻辑似乎已经足够封装,但是,您可能需要检查方法
写入
和读取
是否应保持公共
,或者它们是否应改为私有
。尽量减少公共方法的数量有助于实现更高级别的封装。您的简化版本忽略了最重要的方面:write()
和read()
调用是异步的
因此,函数实际上不会导致递归,请参见最近的答案:
async\u read(…)
和async\u write(…)
的“不同寻常”之处在于,函数在实际执行IO操作之前返回,更不用说完成了。实际执行是在不同的时间表上完成的
为了向“调用者”发回完成信号,异步调用通常采用一个完成处理程序,该处理程序将通过IO操作的结果被调用
在该完成处理程序中,通常会看到通信通道的结束,或者计划下一个IO操作。这被称为异步调用链,在许多支持异步操作的语言中非常突出
这需要一些时间来适应,但最终你会习惯这种模式
考虑到这一点,请重新查看其中一个提振示例,看看便士是否会下降:
void handle\u connect(const boost::system::error\u代码和错误)
{
如果(!错误)
{
boost::asio::异步读取(套接字读取),
boost::asio::buffer(read_msg_u.data(),chat_message::header_length),
boost::bind(&chat_client::handle_read_头,这个,
boost::asio::占位符::错误);
}
}
无效句柄读取头(常量boost::system::error\u代码和错误)
{
if(!error&&read\u msg\u.decode\u header())
{
boost::asio::异步读取(套接字读取),
boost::asio::buffer(read_msg_u.body(),read_msg_u.body_ulength()),
boost::bind(&chat\u client::handle\u read\u body,这个,
boost::asio::占位符::错误);
}
其他的
{
不要关闭();
}
}
无效句柄\u读取\u正文(常量boost::system::error\u代码和错误)
{
如果(!错误)
{
std::cout.write(read_msg_uu.body(),read_msg_uu.body_ulength());
std::cout如果您正在执行正确的尾部调用,编译器应该优化它们以防止调用堆栈溢出。如何定义“正确”?这意味着控制不必返回给调用方,即返回f(x);
是尾部调用且int y=f(x);return y;
不是。不,这里不涉及尾部递归。如果不解决异步问题,您就无法回答有关异步控制流的问题。(我理解,因为OP基本上对其代码进行了中性化,以消除其符号,但他肯定在描述和标记中提到了。)好的观点。我只是指代码,不是从原始Asio代码的角度,而是从OP发布的代码。
bool replied = true;
while (!error) {
if (replied) read();
else {
write();
replied = !replied;
}
}
void handle_connect(const boost::system::error_code& error)
{
if (!error)
{
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
boost::bind(&chat_client::handle_read_header, this,
boost::asio::placeholders::error));
}
}
void handle_read_header(const boost::system::error_code& error)
{
if (!error && read_msg_.decode_header())
{
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
boost::bind(&chat_client::handle_read_body, this,
boost::asio::placeholders::error));
}
else
{
do_close();
}
}
void handle_read_body(const boost::system::error_code& error)
{
if (!error)
{
std::cout.write(read_msg_.body(), read_msg_.body_length());
std::cout << "\n";
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
boost::bind(&chat_client::handle_read_header, this,
boost::asio::placeholders::error));
}
else
{
do_close();
}
}
void do_write(chat_message msg)
{
bool write_in_progress = !write_msgs_.empty();
write_msgs_.push_back(msg);
if (!write_in_progress)
{
boost::asio::async_write(socket_,
boost::asio::buffer(write_msgs_.front().data(),
write_msgs_.front().length()),
boost::bind(&chat_client::handle_write, this,
boost::asio::placeholders::error));
}
}
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
write_msgs_.pop_front();
if (!write_msgs_.empty())
{
boost::asio::async_write(socket_,
boost::asio::buffer(write_msgs_.front().data(),
write_msgs_.front().length()),
boost::bind(&chat_client::handle_write, this,
boost::asio::placeholders::error));
}
}
else
{
do_close();
}
}
void do_close()
{
socket_.close();
}