C ++构造函数继承(从派生类调用构造函数)

时间:2014-10-10 15:58:49

标签: c++ inheritance boost constructor

我在继承/调用基类的构造函数时遇到了麻烦。我将该类基于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 ++菜鸟,所以非常感谢任何帮助!

2 个答案:

答案 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进行网络编程,如果你甚至不知道类和构造函数的基础知识就移动语义。也许你应该从小做起。