首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >定义没有默认可构造数据成员的空默认构造函数。

定义没有默认可构造数据成员的空默认构造函数。
EN

Stack Overflow用户
提问于 2015-10-24 15:08:23
回答 2查看 230关注 0票数 0

请考虑以下示例:

代码语言:javascript
运行
复制
class MyWrapper {
    public:
        MyWrapper() {};
    private:
       ThirdPartyLibraryType impl;
};

假设ThirdPartyLibraryType没有默认的构造函数,我无法帮助它,因为它是第三方库类型。然后,这段代码将不会编译,因为默认构造函数MyWrapper()必须调用ThirdPartyLibraryType的默认构造函数。现在,我只希望默认构造函数什么也不做,因为我使用默认构造函数的用例如下:

代码语言:javascript
运行
复制
std::array<MyWrapper,10> myArray;
for (int i=0;i<10;++i) {
    myArray[i] = generateMyWrapper(...);
}

是否有强制生成默认构造函数的方法?(没有开销,我不想使用ThirdPartyLibraryType*有数据成员的明显解决方案)

编辑:到目前为止,我使用的方法类似于Yakk提出的方法,它不依赖默认的构造函数,但我认为成员函数调用的情况很难看:

代码语言:javascript
运行
复制
template<class T, size_t N, class C, class CF>
std::array<T,N> gen_array(C const& obj, CF&& f) {
    ...
    use obj.f
    ...
}

class MyClass {

    MyWrapper generateMyWrapper(int i) const { ... }

    auto genMyWrapperTypeArray() const {
        return 
            gen_array<
                 MyWrapper,10,MyClass,
                 MyWrapper(MyClass::*)(int) const
            > (
                *this, &MyClass::generateMyWrapper
            );
    }
}

我还没有对它进行测试,我的要点是,如果语法不完全相同,它仍然比我在可用默认构造函数时使用的简单for循环复杂得多。

EN

回答 2

Stack Overflow用户

发布于 2015-10-24 15:18:14

std::experimental::optional或boost等价物的开销并不大,但“这可能是,也可能不是建造的”。

一个不安全的等价物是std::aligned_storage_t,您可以在那里进行构造。问题正在毁灭,你需要知道它是否被建造。

一个更好的选择可能是选择整个数组,而根本没有零参数ctor。打包构建每个参数所需的内容,创建一个构造函数,而不是一个循环。

代码语言:javascript
运行
复制
template<class T, size_t...Is, class F>
std::array<T,sizeof...(Is)> gen_array(
  std::index_sequence<Is...>, F&&f
){
  return {{f(Is)...}};
)


template<class T, size_t N, class F>
std::array<T,N> gen_array(
  F&&f
){
  return gen_array(std::make_index_sequence<N>{}, f);
)

上面的函数调用传递的lambda,其中包含每个元素的索引,以构造元素。

票数 1
EN

Stack Overflow用户

发布于 2015-10-24 15:27:02

如果ThirdPartyLibraryType没有默认构造函数,则这很可能是由于有效的设计决策/原因造成的。

然后有两种方法:

  • 要么为非默认构造函数找到一些合适的参数,然后在包装器中使用这些参数;
  • 或者延迟ThirdPartyLibraryType的构造,直到知道要使用哪个构造函数和使用哪些参数。

第一种方法如下所示:

代码语言:javascript
运行
复制
class MyWrapper {
    public:
        MyWrapper() : impl(/*parameters that you've selected*/) {};
    private:
       ThirdPartyLibraryType impl;
};

也许它适合您的需要,因为您已经知道要使用哪个构造函数参数,或者因为您可以负担得起构造一个廉价的对象并在以后重写它。但这并不总是个好主意..。

第二种方法将使用您想要避免的指针。这种方法有许多优点:

  • 您可以像在示例中那样构造巨大的默认初始化数组,并用生成的对象覆盖不昂贵的默认包装。
  • 您尊重您所依赖的库的设计,只构造有意义的对象。
  • 您可以减少对第三方库的依赖:需要包装器的编译单元不需要知道第三方类型,也不需要包含第三方库的头(前向声明就足够了)。

事实上,显而易见的指针方法将使包装器实现PIMPL成语

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33319649

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档