确保const指针的成员变量的常量

时间:2015-09-03 08:40:23

标签: c++ pointers compiler-errors const

为什么这段代码能够顺利编译?

λ> parseOnly keyValuePair  "k: v"
Right ("k","v")

λ> parseOnly msg "k: v\r\nk2: v2\r\n"
Right [("k","v"),("k2","v2")]

λ> parseOnly msgs  "k1: v1\r\nk2: v2\r\n\r\nk3: v3\r\nk4: v4"
Right [[("k1","v1"),("k2","v2")],[("k3","v3"),("k4","v4")]]

λ> parseOnly msgs "k: v"
Right [[("k","v")]]

我希望将class myvector { public: myvector() { begin = new double[10]; end = begin+10; } ~myvector() { delete[] begin; } double *begin; double *end; }; class VectorWorker { public: VectorWorker(){} void doWork(const myvector *v) { for (int i=0;i<10;i++) v->begin[i] = i; // I don't want this to compile! I'd prefer compiler says me I can't modify v->begin } void doWork2(const myvector *const v) const { for (int i=0;i<10;i++) v->begin[i] = i; // I don't want this to compile! I'd prefer compiler says me I can't modify v->begin } void doWork3(const myvector &v) { for (int i=0;i<10;i++) v.begin[i] = i; // I don't want this to compile! I'd prefer compiler says me I can't modify v->begin } }; int main(int, char*[]) { myvector x; VectorWorker work; work.doWork(&x); work.doWork2(&x); work.doWork3(x); return 0; } 传递给const myvector *v方法,应该确保VectorWorker::doWork中的变量保持不变,但实际上它们已被修改。如何确保myvector方法允许只读操作?

实际上,我无法将doWorkdouble *begin变量修改为double *end,因为它们来自第三方库。但是,即使通过const double *,我怎么能确定它们在通过它们所属类的实例时保持不变?

代码在coliru中可用:http://coliru.stacked-crooked.com/a/bb43fbebebdb5872

3 个答案:

答案 0 :(得分:2)

使用访问者:

class myvector
{
public:
    //previous code

    const double* get_begin() const { return begin; }
    const double* get_end() const { return end; }
    double* get_begin() { return begin; }
    double* get_end() { return begin; }
private:
    double *begin;
    double *end;
};

答案 1 :(得分:0)

所以你不能用双ptr来做。如果你真的希望它“正常工作”,那么你可以创建一个自定义的DoublePtr类型:

class DoublePtr
{
public:
    DoublePtr() { _ptr = 0; }
    DoublePtr(double* ptr) { _ptr = ptr; }
    //index operators provide lookups
    double& operator[](int pos) {
        return _ptr[pos];
    }
    const double& operator[](int pos) const {
        return _ptr[pos];
    }

    //casts for backward compatibility
    operator double*() {
        return _ptr;
    }
    operator const double*() const {
        return _ptr;
    }
private:
    double* _ptr;
};

class myvector
{
public:
    myvector()
    {
        buffer = new double[10];
        begin = DoublePtr(buffer);
        end = DoublePtr(buffer+10);
    }
    ~myvector()
    {
        delete[] begin;
    }

    DoublePtr begin;
    DoublePtr end;
private:
    double* buffer;
};

然后,VectorWorker代码根本不需要更改。

说了这么多 - 如果你可以使用它们,访问者看起来似乎是一种更好的方式。

答案 2 :(得分:0)

const不是传递性的;而指针本身将是const(你可以设置'begin'),它指向的值不是。

所以你不能在不修改myvector(你说它不是一个选项)或仅通过只提供const访问的包装器访问它的情况下得到这种行为。

它不完全是一个理想的解决方案 - 最好修复myvector憎恶(这个库来自哪个?)。

e.g。

class myvectorconst
{
private:
    myvector* vec_;
public:
    myvectorconst(myvector* vec) : vec_(vec) {}
    double const* begin() const { return vec_->begin; }
};

class VectorWorker
{
public:
    VectorWorker(){}
    void doWork(const myvectorconst& v)
    {
        for (int i=0;i<10;i++)
            v->begin()[i] = i; // Won't compile.
    }
// ...
};