C++11;非静态数据成员初始化可以访问其他数据成员吗?

标签 c++ gcc lambda c++11 mingw

我真的很喜欢 C# 中的属性的想法,并且作为一个小的副项目,我一直在修补在 C++ 中实现它们的想法。我遇到了这个例子 https://stackoverflow.com/a/5924594/245869这看起来相当不错,但我忍不住认为 lambda 表达式和非静态数据成员初始化可能使使用一些非常好的语法来实现这个想法成为可能。这是我的实现:

#include <iostream>
#include <functional>

using namespace std;


template< typename T >
class property {

public:
    property(function<const T&(void)> getter, function<void(const T&)> setter)
        : getter_(getter),
          setter_(setter)
    {};

    operator const T&() {
        return getter_();
    };

    property<T>& operator=(const T& value) {
        setter_(value);
    }

private:
    function<const T&(void)> getter_;
    function<void(const T&)> setter_;

};


class Foobar {

public:
    property<int> num {
        [&]() { return num_; },
        [&](const int& value) { num_ = value; }
    };

private:
    int num_;

};


int main() {
    // This version works fine...
    int myNum;
    property<int> num = property<int>(
        [&]() { return myNum; },
        [&](const int& value) { myNum = value; }
    );
    num = 5;

    cout << num << endl;  // Outputs 5
    cout << myNum << endl;  // Outputs 5 again.

    // This is what I would like to see work, if the property
    // member of Foobar would compile...
    // Foobar foo;
    // foo.num = 5;

    // cout << foo.num << endl;

    return 0;
}

我可以正常使用我的属性类[参见 main()] 中的示例],但是带有 g++4.7 的 MinGW 并不特别关心我尝试将该属性用作数据成员:

\property.cpp: In lambda function:
\property.cpp:40:7: error: invalid use of non-static data member 'Foobar::num_'

所以我的属性实现的概念似乎有效,但它可能是徒劳的,因为我无法从我的 lambda 函数访问其他数据成员。我不确定标准如何定义我在这里尝试做的事情,我是完全不走运,还是我只是没有在这里做某事?

最佳答案

您的属性是与包含对象(property<int> 的实例)不同的对象(Foobar 的实例)。因此,它的成员函数被传递给一个不同的 this。 ,而不是您需要访问的 num_ ——所以你不能那样做。如果 lambda 是在 Foobar 的非静态成员函数中定义的, 他们会捕获该函数的 this参数并且可以访问封闭对象的成员(明确地,作为 this->num_ )。但是 lambda 是在类中定义的,其中非静态数据成员实际上并不存在。如果 lambda 确实可以访问 num_ ,这num_ ,其中 Foobar 的实例, 会是这样吗?

我看到的最简单的解决方案是让属性存储指向封闭对象的指针。这样,它就可以自由访问其非静态成员。缺点是声明稍微复杂一些(您必须执行 property<int, Foobar> num )并且您需要通过传递 this 来初始化属性指针。所以你不能在类中这样做,它必须在构造函数的初始化列表中,因此否定了 C++11 的数据成员初始化的优势。

那时,this lambdas 无论如何都可以捕获(按值,而不是按引用!)所以如果您将属性的初始化移动到 Foobar 的构造函数,您的代码实际上可以进行最小的更改:

Foobar::Foobar():
    num {
        [this]() { return this->num_; },
        [this](const int& value) { this->num_ = value; }
    }
{
}

有谁知道this ,传递给恰好被调用的任何构造函数,是否可用于类定义中的非静态成员初始化?我怀疑不是,但如果是的话,相同的构造将在类定义中起作用。

关于C++11;非静态数据成员初始化可以访问其他数据成员吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10333736/

相关文章:

c# - C# 6.0 语法错误

c++ - 没有可用的可以执行此转换的用户定义转换运算符,或者无法调用该运算符

c++ - (VS2015) 尝试用初始化列表中的数据填充静态映射

c++ - 通过返回引用的方法修改私有(private)对象属性

c - 文件处理 : Extra characters in output

C : Undefined reference error

c - 采用 2 个位置参数的 C 语言示例应用程序

c# - 构建表达式树以动态排序 LINQ 中的字典字典

c++ - 迈耶斯单例范围

c++ - 在 C++ 中读写文件