C++:如何创建一个临时对象,包含一个指针 - 常量或非常量,具体取决于上下文

C++: How to create a temporary object, containing a pointer - const or non-const, depending on context?

本文关键字:常量 非常 上下文 取决于 指针 临时对象 何创建 创建 C++ 一个 包含一      更新时间:2023-10-16

我想在向量中保存一些Data结构。这些结构通过索引(而不是指针(引用其他结构,以节省内存并使序列化更容易。为了遵循这些索引,我创建了一个类DataView,它为它提供了一个舒适的界面。它看起来像这样:

#include <iostream>
#include <vector>
struct Data
{
    int id_next;
    int id_prev;
    int value;
};
class Foo;
class DataView
{
    Foo * foo;
    int index;
public:
    DataView( Foo * foo_, int index_ )
        : foo( foo_ ), index( index_ )
    {
    }
    DataView next() const;
    DataView prev() const;
    int value() const;
    int & value();
    int id() const
    {
        return index;
    }
};
class Foo
{
    std::vector<Data> data;
public:
    friend class DataView;
    DataView dataview( int index )
    {
        return DataView( this, index );
    }
    Foo()
    {
        data.resize( 5 );
        for ( int i = 0; i < (int)data.size(); i++ )
        {
            data[i].id_next = (i + 1) % data.size();
            data[i].id_prev = (i + 4) % data.size();
            data[i].value = i * i;
        }
    }
    void write_cycle( int start_index ) // const
    {
        DataView seek = dataview( start_index );
        do
        {
            std::cout << "index " << seek.id() << " value " << seek.value() << std::endl;
            seek = seek.next();
        } while ( seek.id() != start_index );
    }
};
DataView DataView::next() const
{
    return DataView( foo, foo->data[index].id_next );
}
DataView DataView::prev() const
{
    return DataView( foo, foo->data[index].id_prev );
}
int DataView::value() const
{
    return foo->data[index].value;
}
int & DataView::value()
{
    return foo->data[index].value;
}
int main()
{
    Foo foo;
    foo.write_cycle( 3 );
    foo.dataview( 2 ).value() = 11;
    foo.write_cycle( 3 );
    return 0;
}

如果我必须区分dataview方法的常量和非常量变体,就会出现问题。事实上,write_cycle应该是恒定的,因为它不会改变任何东西。但是,如果我取消注释限定符const我会收到编译器错误。

错误:将"const Foo"作为"this"参数传递会丢弃限定符 [-fallowive]

如何编写包含常量或非常量foo指针的DataView,具体取决于它的构造函数是用常量还是非常量指针调用的?

你说:

这些结构通过索引(而不是指针(引用其他结构,以节省内存并使序列化更容易。为了遵循这些索引,我创建了一个类DataView,它为它提供了一个舒适的界面。

这向我表明您不需要支持:

foo.dataview( 2 ).value() = 11;

使用 DataView读取数据。如果您同意这一点,您可以更改DataView以存储Foo const*。然后,您可以摆脱非const版本的DataView::value()

class DataView
{
    Foo const* foo;
    int index;
public:
    DataView( Foo const* foo_, int index_ )
        : foo( foo_ ), index( index_ )
    {
    }
    DataView next() const;
    DataView prev() const;
    int value() const;
    // Don't need this.
    // int & value();
    int id() const
    {
        return index;
    }
};

如果一个方法const ,则不允许它执行或提供的任何操作来更改实例。这包括方法调用的任何函数或其他方法,以及对该方法返回的任何成员的引用必须const,以便将来不能使用它们来修改对象。

因此,如果write_cycleconst那么dataview必须const并且DataView必须有一个接受const Foo *的构造函数。这意味着还必须const DataView::foo接受const Foo *的分配。如果DataView的客户端希望操纵存储的Foo,这可能是一个问题。

最终结果,如果没有一堆额外的工作,write_cycle就无法const

要向用户添加R Sahu's关于将Foo保留在Dataview内作为const的答案,因为它将充当read only类并且不应该修改Foo; 您可以将此函数添加到类Foo's以更新其值:

void Foo::updateValue( int index, const int& value ) {
    if ( index < 0 || index >= data.size() ) {
        return;
    }
    data[index].value = value;
}

然后在主文件.cpp内部将如下所示:

Foo foo;
std::cout << "writing cycle of 3" << std::endl;
foo.write_cycle( 3 );
std::cout << "updating index 2 with value of 11" << std::endl;
foo.updateValue( 2, 11 );
std::cout << "writing cycle of 3" << std::endl;
foo.write_cycle( 3 );