Const和非const c ++构造函数

时间:2014-04-26 16:29:07

标签: c++ const

在C ++ 03(或更早版本)中是否有办法编写一个可以存储const或非const指针的类,并适当地处理访问?以非功能性“有时会议”类的用法为例:

class SometimesConst
{
    public:
    SometimesConst(int * buffer) : buffer(buffer) {} // Needs const qualifier?

    int* get() { return buffer; } // Needs const qualifier?

    void increment() { counter++; }

    private:
    int * buffer; // Needs const qualifier?
    int counter;
};

void function(int * n, const int * c)
{
    // These are both okay
    SometimesConst wn(n);
    SometimesConst wc(c);

    // Reading the value is always allowed
    printf("%d %d", wn.get()[0], wc.get()[0]);

    // Can increment either object's counter
    wn.increment();
    wc.increment();

    // Can set non-const pointer
    wn.get()[0] = 5;

    // Should generate a compiler error
    wc.get()[0] = 5;
}

创建const SometimesConst不允许修改对象的counter属性。一个类是否可以设计为具有编译时const安全性的输入对象,只有它们作为const传递?

3 个答案:

答案 0 :(得分:2)

不,不是你想要使用它的方式。在编译时具有不同行为的唯一方法是使用不同的类型。但是,您可以使用起来相当容易:

#include <stdio.h>

template <typename T>
class SometimesConst
{
  public:
    SometimesConst(T* buffer) : buffer(buffer) { }
    T* get() { return buffer; }
    void increment() { ++counter; }
  private:
    T *buffer;
    int counter;
};

typedef SometimesConst<const int> IsConst;
typedef SometimesConst<int> IsNotConst;

void function(int * n, const int * c)
{
  IsNotConst wn(n);
  IsConst wc(c);

  // Reading the value is always allowed
  printf("%d %d", wn.get()[0], wc.get()[0]);

  // Can increment either object's counter
  wn.increment();
  wc.increment();

  // Can set non-const pointer
  wn.get()[0] = 5;

  // Should generate a compiler error
  wc.get()[0] = 5;
}

答案 1 :(得分:1)

已经 的语言允许你用一个简单的类来做这个;通过const级联访问成员的方式(与mutable成员counter相结合,您已指明该成员应该始终可变),您可以同时提供只读和对缓冲区的读写访问非常容易:

class C
{
public:
    C(int* buffer) : buffer(buffer) {}

    const int* get() const { return buffer; }
    int* get() { return buffer; }

    void increment() const { counter++; }

private:
    int* buffer;
    mutable int counter;
};

void function(int* n)
{
    // These are both okay
    C wn(n);
    const C wc(n);

    // Reading the value is always allowed
    printf("%d %d", wn.get()[0], wc.get()[0]);

    // Can increment either object's counter
    wn.increment();
    wc.increment();

    // Can set non-const pointer
    wn.get()[0] = 5;

    // Generates a compiler error
    wc.get()[0] = 5;
}

您可以通过 int*const int*整齐地安排课程的实施。这两个语言对你的班级来说会产生完全不同的语义,所以如果你真的需要它,你应该把它分成两个。

幸运的是,模板使这很容易:

template <typename T>
class C
{
public:
    C(T* buffer) : buffer(buffer) {}

    const T* get() const { return buffer; }
    T* get() { return buffer; }

    void increment() const { counter++; }

private:
    T* buffer;
    mutable int counter;
};

现在C<int>如上所述,但只有C<const int> 提供对缓冲区的只读访问权限,即使C<const int>对象本身不是标记为const

void function(int* n1, const int* n2)
{
    C<int>             a(n1);
    C<const int>       b(n2);
    const C<int>       c(n1);
    const C<const int> d(n2);

    // Reading the value is always allowed
    printf("%d %d %d %d",
       a.get()[0], b.get()[0],
       c.get()[0], d.get()[0]
    );

    // Incrementing the counter is always allowed
    a.increment();
    b.increment();
    c.increment();
    d.increment();

    // Can set non-const pointer
    a.get()[0] = 5;

    // Cannot set const pointer, or const/non-const pointer behind const object
    //b.get()[0] = 5;
    //c.get()[0] = 5;
    //d.get()[0] = 5;
}

Live demo

答案 2 :(得分:-1)

如果你想存储两个必须在一个类中以不同方式处理的不同内容,我认为存在设计问题。但是,你可以这样做:

struct X{};

class A
{   
    public:
        A(const X*) { cout << "const" << endl; }
        A(X*)       { cout << "non const" << endl; }

};  

int main()
{   
    const X x1; 
    X x2; 

    A a1(&x1);
    A a2(&x2);
}   

预期输出:

const
non const