我在继承/调用基类的构造函数时遇到了麻烦。我将该类基于Boost.Asio示例。
这里是父类:
#ifndef CLIENT_HPP
#define CLIENT_HPP
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
using boost::asio::ip::tcp;
class client : public std::enable_shared_from_this<client> {
public:
client(tcp::socket socket) : socket_(std::move(socket)) {
}
void start() {
}
tcp::socket socket_;
};
#endif
以下是子类:
#ifndef PENGUIN_HPP
#define PENGUIN_HPP
#include "Client.hpp"
class penguin : public client {
public:
penguin() : client(socket_) {
}
};
#endif
这就是我初始化企鹅类
的方式std::make_shared<penguin>(std::move(socket_))->start();
socket _ 这里是服务器的 tcp :: socket 。
我是C ++菜鸟,所以非常感谢任何帮助!
答案 0 :(得分:3)
首先,让我们澄清一下。在C ++中,构造函数不是继承的。类层次结构中构造函数的行为可能会使构造函数有时被继承,有些人会认为我过于迂腐,但我认为理解这种区别很重要。
现在的问题是如何在派生类中调用基类的构造函数&#39;构造函数。答案是在派生类中进行的。构造函数初始化列表 - 就像你正在做的那样。
然而,你实际上是如何解决它的问题
penguin() : client(socket_) {}
此处,socket_
是基类client
的成员(除非您的帖子中有错误信息)。在 socket_
对象被实例化之前,client
被引用,因此它甚至还不存在。这是一种鸡蛋问题。为了实例化client
,您需要socket_
,但为了引用socket_
,您需要实例化client
,并且节拍继续......
我没有简明扼要的建议,我可以帮你解决你遇到的这个问题,因为不幸的是,这并不容易解决。这里真正的问题是你的设计被破坏了。由于您在基类和该基类的成员之间引入了循环依赖性,它已经被破坏了。你需要重新审视你的设计。
答案 1 :(得分:0)
在此示例中,您可以简化您尝试做的事情:
class foo
{
public:
foo(int x);
protected:
int m_x;
};
class bar : public foo
{
public:
bar();
};
// in bar.cpp:
bar::bar()
:foo(foo::x)
{
}
显然没有意义。您无法使用自己尚不存在的数据成员初始化对象。在您的情况下,您尝试使用自己的client
初始化socket_
。您需要先在其他地方构建一个套接字。当您声明一个类的实例时,它将按照从其最基类型到其最派生类型(客户端构造函数先完成,然后是penguin等)的顺序构造,并且它以相反的顺序被破坏。企鹅构造函数不会“覆盖”客户端构造函数。
你也正在初始化你的企鹅实例,好像它在构造函数中需要一个套接字参数,当它没有时。如果你希望你的企鹅接受一个套接字供其父的构造函数使用,那么在penguin的构造函数中添加一个套接字参数。在任何情况下,您仍然需要单独构造一个套接字并将其传递给构造函数。
我也很好奇你对C ++ noob的定义是什么,以及你为什么要尝试使用boost :: asio进行网络编程,如果你甚至不知道类和构造函数的基础知识就移动语义。也许你应该从小做起。