C ++ 11;非静态数据成员初始化可以访问其他数据成员吗? [英] C++11; Can non-static data member initializations access other data members?

查看:159
本文介绍了C ++ 11;非静态数据成员初始化可以访问其他数据成员吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我非常喜欢C#中的属性概念,作为一个小小的项目,我一直在修改用C ++实现它们的想法。我遇到了这个示例 https://stackoverflow.com/a/5924594/245869 ,这看起来相当不错,但我不能没有帮助,但认为lambdas和非静态数据成员初始化可能会使这个想法使用一些非常好的语法成为可能。这是我的实现:

  #include< iostream> 
#include< functional>

使用namespace std;


模板< 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_();
};

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

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

};


class Foobar {

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

private:
int num_;

};


int main(){
//此版本正常工作...
int myNum;
属性< int> (
[&](){return myNum;},
[&](const int& value){myNum = value;}
);
num = 5;

cout<< num<< ENDL; //输出5
cout<< myNum<< ENDL; //再次输出5。

//这是我希望看到的工作,如果Foobar的属性
//会编译...
// Foobar foo;
// foo.num = 5;

// cout<< foo.num<< ENDL;

返回0;
}

我可以正常使用我的属性类[请参阅main() ,但是使用g ++ 4.7的MinGW并不特别关心我使用该属性作为数据成员的尝试:

  \\ \\property.cpp:在lambda函数中:
\property.cpp:40:7:错误:无效使用非静态数据成员'Foobar :: num_'



所以看起来我的属性实现的概念可行,但它可能是徒劳的,因为我无法从我的lambda函数访问其他数据成员。我不知道这个标准是如何定义我在这里做什么的,我完全不幸运,或者我只是没有在这里做什么?

解决方案

您的属性是包含对象(的实例)中的一个不同对象(属性< / code> foob​​ar的)。因此,它的成员函数会传递一个不同的这个,而不是你需要访问的那个 num _ - 所以你不能那样做。如果lambda是在 Foobar 的非静态成员函数中定义的,则它们会捕获该函数的 this 参数,并且将有权访问封闭对象的成员(明确地,如 this-> num _ )。但lambda在类中定义,其中非静态数据成员实际上不存在。如果lambda 有权访问 num _ ,其中 num _ code> Foobar ,会是这样吗?



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



此时,这个可用于lambda表达式(通过值而不是引用!),所以你的代码实际上只需要很少的修改就可以工作你将属性的初始化移动到Foobar的构造函数中:
$ b $ pre $ Foobar :: Foobar():
num {
[this](){return this-> num_; },
[this](const int& value){this-> num_ = value; }
}
{
}

有人知道 this 传递给恰好被调用的任何构造函数,可用于类定义中的非静态成员初始化?我怀疑它不是,但如果是这样,相同的构造可以在类定义中使用。


I really like the idea of properties in C#, and as a little side project, I've been tinkering with the idea of implementing them in C++. I ran into this example https://stackoverflow.com/a/5924594/245869 which seems fairly nice, but I couldn't help but think that lambdas and non-static data member initialization may make it possible to use some very nice syntax with this idea. Here's my implementation:

#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;
}

I can use my property class normally [see the example in main()], but MinGW with g++4.7 doesn't particularly care for my attempt at using the property as a data member:

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

So it seems the concept of my property implementation works, but it might be in vain because I can't access other data members from my lambda functions. I'm not sure how the standard defines what I'm trying to do here, am I completely out of luck, or am I just not doing something right here?

解决方案

Your property is a different object (instance of property<int>) from the containing object (instance of Foobar). As such, its member functions get passed a different this, not the one you'd need to access num_ -- so you can't do it that way. If the lambdas were defined in a non-static member function of Foobar, they would have captured that function's this argument and would have had access to the enclosing object's members (explicitly, as this->num_). But the lambdas are defined in the class, where the non-static data members don't actually exist. If the lambdas did have access to num_, which num_, of which instance of Foobar, would have been that?

The easiest solution that I see is for the property to store a pointer to the enclosing object. That way, it can freely access its non-static members. The downside is that the declaration is slightly more complex (you'd have to do property<int, Foobar> num) and you'd need to initialize the property by passing the this pointer. So you won't be able to do it in the class, it would have to be in the constructor's initialization list, hence negating the advantage of C++11's data member initialization.

At that point, this would be available to the lambdas to capture anyway (by value, not by reference!) so your code would actually work with minimal changes, if you moved the initialization of the property to Foobar's constructor(s):

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

Does anyone know whether this, as passed to whatever constructor happens to be invoked, is available for non-static member initialization in the class definition? I suspect it isn't, but if it were, the same construction would work inside the class definition.

这篇关于C ++ 11;非静态数据成员初始化可以访问其他数据成员吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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