0

我正在使用一个定义一些数据类型类的库,这些类通常实现为围绕 std::vector<> 的紧密包装器。类型层次结构有好几层深,大多只添加了详细的构造函数。

我的问题:基类将其 std::vector 定义为私有(这很好),但只添加了一个访问器方法作为 const。派生类甚至无法访问它。库看起来像这样(为了清楚起见,简称):

template <class T> class BaseList
{
public:
    BaseList (const T data0) : data_ (1) { 
       data_[0] = data0; }

    const T & operator[] (const size_t nr) const { 
       // does out off bounds check here       
       return data_[nr]; }

private:
    std::vector<T> data_;
}

class FancyClass : public BaseList<SomeEnumType>
{
public:
    FancyClass (const SomeOtherEnumType data0) 
        : BaseList<SomeEnumType> ( static_cast<SomeEnumType> (data)) 
        {}
}

现在我看到了, const 定义完全是假的。没有内部方法依赖于真正恒定的向量,我在外部代码中也没有。

我喜欢做的就是这样:

strukt MyType {
    FancyClass myData;
    bool otherData;
}

int main() {
    MyType storage = {FancyClass(0), false};

    storage.myData[0] = 5;
}

由于 const-ness,这当然不起作用。(“分配只读位置”)

责任完全在我这边:我可以做一些 const_cast 魔法来使这个结构可写吗?我知道的唯一另一种可能性是在我的代码中完全复制类型层次结构,但这仍然会给我留下很多强制转换或 toFancyClass() 函数,以便在我接口库代码时调用。

有任何想法吗?谢谢!

(请不要评论库的代码质量。如果我可以改变它,我不会问这个问题......)

4

3 回答 3

1

现在我看到了, const 定义完全是假的。没有内部方法依赖于真正恒定的向量,我在外部代码中也没有。

方法上的 const 限定符并不意味着它依赖于恒定的向量。这意味着该方法不会修改对象的状态。添加它是为了编译以下代码。

void f(const FancyClass a)
{
    cout<<a[0];
}

如果没有方法上的 const 限定符,上面的代码将无法编译[]

无论如何,以下应该工作

SomeEnumType & r = const_cast<SomeEnumType &>(storage.myData[0]);

r = b;

类型b在哪里enumSomeEnumType

但是,如果您的storage对象实际上是一个 const 对象,那么它将导致未定义的行为。

于 2012-12-03T13:47:37.847 回答
1

最简单的方法是添加 operator[] 的非常量版本。否则,您可能会通过使用 using 抛弃常量来导致 UB const_cast

您可以像这样丢弃 constness:

int main() {
    MyType storage = {FancyClass(0), false};

    const_cast< SomeEnumType& >( storage.myData[0] ) = 5;
}
于 2012-12-03T13:30:49.303 回答
0

通常 operator[] 成对出现一个可变版本和一个 const 版本..(参见:运算符重载

当然有一个基于 const_cast 的解决方案,但它涉及未定义的行为(你不能在抛弃 const 之后更改值!)

于 2012-12-03T13:33:47.827 回答