Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
类成员函数在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 - Fatal编程技术网

类成员函数在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+;中相互调用的优势是什么+;? 我是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++实现了许多编程范例。这些范例也由许多其他编程语言实现。与您正在讨论的内容相

这是我的看法:

关于递归 导致堆栈溢出的一种方法是让函数递归地调用自身,使调用堆栈溢出。一组以循环方式相互调用的函数将等价于此,因此是的,您的直觉是正确的

该算法的迭代版本,如您描述的循环,可以防止这种情况

现在,另一件可以防止堆栈溢出的事情是存在可以针对尾部递归进行优化的代码。尾部递归优化需要一个实现此功能的编译器。大多数主要的编译器都实现了它。您提到的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();
  }