如何在库中解决'const'定义

时间:2012-12-03 13:26:19

标签: c++ const

我正在使用一个库来定义一些数据类型类,这些类通常作为std :: vector<>周围的紧包装实现。类型层次结构是几层深层,大多只添加精心构造的构造函数。

我的问题:基类将其std :: vector定义为private(很好),但只将constor方法添加为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_cast魔法可以让这个结构可写? 我知道的唯一另一种可能性是在我的代码中完全复制类型层次结构,但是这仍然会让我在接口库代码时调用很多强制转换或toFancyClass()函数。

任何想法?谢谢!

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

3 个答案:

答案 0 :(得分:1)

最简单的是添加运算符[]的非const版本。否则,您可能会通过使用const_cast来丢弃常量来生成UB。

你可以扔掉这样的常量:

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

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

答案 1 :(得分:1)

  

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

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

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

如果没有[]方法上的const限定符,上面的代码就不会编译。

无论如何,以下应该有效

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

r = b;

其中benum

类型的SomeEnumType

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

答案 2 :(得分:0)

通常,operator []有一对mutable和一个const版本..(参见:Operator overloading

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