是否有可能将成员初始化推迟到构造函数体? [英] Is it possible to defer member initialization to the constructor body?

查看:173
本文介绍了是否有可能将成员初始化推迟到构造函数体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类有一个对象作为一个没有默认构造函数的成员。我想在构造函数中初始化这个成员,但似乎在C ++我不能这样做。这是类:

  #include< boost / asio.hpp> 
#include< boost / array.hpp>

使用boost :: asio :: ip :: udp;

template< class T>
class udp_sock
{
public:
udp_sock(std :: string host,unsigned short port);
private:
boost :: asio :: io_service _io_service;
udp :: socket _sock;
boost :: array< T,256> _buf;
};

template< class T>
udp_sock< T> :: udp_sock(std :: string host =localhost,
unsigned short port = 50000)
{
udp :: resolver res(_io_service);
udp :: resolver :: query query(udp :: v4(),host,spec);
udp :: endpoint ep = * res.resolve(query);
ep.port(port);
_sock(_io_service,ep);
}

编译器告诉我基本上它找不到udp的默认构造函数:: socket,通过我的研究,我理解C ++在调用构造函数之前隐式初始化每个成员。有没有办法做到我想做的方式,或者是Java为主,而不是在C ++中可行?



我解决了问题通过这样定义我的构造函数:

  template< class T& 
udp_sock< T> :: udp_sock(std :: string host =localhost,
unsigned short port = 50000):_sock(_io_service)
{
udp :: resolver res(_io_service);
udp :: resolver :: query query(udp :: v4(),host,spec);
udp :: endpoint ep = * res.resolve(query);
ep.port(port);
_sock.bind(ep);
}



因此我的问题更多是出于好奇心和更好地了解C ++中的OOP

解决方案

定义构造函数时,有两种方法可以初始化属性:




  • 初始值列表

  • 构造函数体



如果你不明确地初始化初始化器列表中的一个属性,它仍然被初始化(通过调用它的默认构造函数)...



本质:

  class示例
{
public:
Example
private:
Bar mAttr;
};

//你写
Example :: Example(){}

//编译器理解
Example :: Example():mAttr ){}

如果底层类型没有默认构造函数, p>

有多种方法可以延迟这个初始化。 标准的方式是使用一个指针:

  class Example {public:Example private:Bar * mAttr; }; 

但我更喜欢使用 Boost.Optional 与合适的访问器:

  class示例
{
public:Example();
private:
Bar& accessAttr(){return * mAttr; }
const Bar& getAttr()const {return * mAttr; }
boost :: Optional< Bar> mAttr;
};

示例:: Example(){mAttr = Bar(42); }因为Boost.Optional意味着在分配上没有开销,并且在解除引用上没有开销(例如,该对象被创建就地),并且携带正确的语义。


I have a class with an object as a member which doesn't have a default constructor. I'd like to initialize this member in the constructor, but it seems that in C++ I can't do that. Here is the class:

#include <boost/asio.hpp>
#include <boost/array.hpp>

using boost::asio::ip::udp;

template<class T>
class udp_sock
{
    public:
        udp_sock(std::string host, unsigned short port);
    private:
        boost::asio::io_service _io_service;
        udp::socket _sock;
        boost::array<T,256> _buf;
};

template<class T>
udp_sock<T>::udp_sock(std::string host = "localhost",
  unsigned short port = 50000)
{
    udp::resolver res(_io_service);
    udp::resolver::query query(udp::v4(), host, "spec");
    udp::endpoint ep = *res.resolve(query);
    ep.port(port);
    _sock(_io_service, ep);
}

The compiler tells me basically that it can't find a default constructor for udp::socket and by my research I understood that C++ implicitly initializes every member before calling the constructor. Is there any way to do it the way I wanted to do it, or is it too "Java-oriented" and not feasible in C++?

I worked around the problem by defining my constructor like this:

template<class T>
udp_sock<T>::udp_sock(std::string host = "localhost",
  unsigned short port = 50000) : _sock(_io_service)
{
    udp::resolver res(_io_service);
    udp::resolver::query query(udp::v4(), host, "spec");
    udp::endpoint ep = *res.resolve(query);
    ep.port(port);
    _sock.bind(ep);
}

So my question is more out of curiosity and to better understand OOP in C++

解决方案

When you define a constructor, you have 2 ways to "initialize" attributes:

  • the initializer list
  • the constructor body

If you do not explictly initialize one of the attributes in the initializer list, it is nonetheless initialized (by calling its default constructor) for you...

So in essence:

class Example
{
public:
  Example();
private:
  Bar mAttr;
};

// You write
Example::Example() {}

// The compiler understands
Example::Example(): mAttr() {}

And this of course fails if the underlying type does not have a Default Constructor.

There are various ways to defer this initialization. The "standard" way would be to use a pointer:

class Example { public: Example(); private: Bar* mAttr; };

However I prefer using Boost.Optional combined with suitable accessors:

class Example
{
public: Example();
private:
  Bar& accessAttr() { return *mAttr; }
  const Bar& getAttr() const { return *mAttr; }
  boost::Optional<Bar> mAttr;
};

Example::Example() { mAttr = Bar(42); }

Because Boost.Optional means that there is no overhead on the allocation and no overhead on the dereferencing (the object is created in place) and yet carries the correct semantic.

这篇关于是否有可能将成员初始化推迟到构造函数体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆