0

看看这段非常简单的代码:

struct A { char* s; };

class B
{
    A* a;

    public: B(const char* s) : a(new A()) {
        int len = strlen(s);
        a->s = new char[len + 1];
        memcpy(a->s, s, len + 1);
    }

    ~B() { delete [] a->s; delete a; }

    const char* c_str() const { return a->s; }

    const B& to_upper() const {
        char* x = a->s;
        int len = strlen(x);
        for (int i = 0; i < len; i++)
        {
            char k = x[i];
            if (k >= 'a' && k <= 'z')
                x[i] -= 32;
        }
        a->say_hi();
        return *this;
    }
};

int main() {
    B b = "hola mundo";
    printf("%s\n", b.to_upper().c_str());
}

有用!!我的问题是……为什么?

to_upper() 方法是 const 并通过“a”修改值指针。好的,我无法执行“a = nullptr;”之类的操作 因为编译器说:“您正在尝试修改只读对象”;但它可以让我修改基础值。这种行为正确吗?不应该像const方法中将“this”的类型转换为“const B*”一样将“a”类型转换为“const A*”吗?

谢谢!

4

2 回答 2

6

方法的 const 转换为对象的 const ,这*this意味着指针内部具有 type 。这里的所有都是它的。不多也不少。例如,这样做的效果与您在 C 语言中看到的没有什么不同。它使指针变为常量,但不影响指针对象。to_upperthisconst B *this->a

实际上,由您决定 的常量是否B传播到 所A指向的对象this->a。该语言使您可以完全自由地做出此决定。它被称为“概念常数”(与“物理常数”或“逻辑常数”相对)。编译器只观察并强制执行逻辑常量,而constOOP 中关键字的目的远不止于此:它允许您在设计中实现概念常量的想法。

如果A对象被认为是 的一个组成部分B,那么 的 constness 也B应该意味着 的 constness A。但这是你必须手动观察和强制执行的事情(或者一些智能指针类可以帮助你)。

如果Aobject 是一个独立对象,恰好只是从引用B,那么 constness ofB不一定意味着 constness of A

编译器不会对此做出任何决定,因为编译器不知道您要实现的对象关系。在您的设计中,在我看来,该A对象实际上是 的一个组成部分B,这意味着您不应该将您的声明to_upperconst. 这是一个修改功能。它改变了用户所感知的值B。通过声明你本质上是在向用户“撒谎” to_upperconst

于 2012-07-02T03:30:49.857 回答
1

const 函数不得修改类成员。'pointee by a' 不是该类的成员。

于 2012-07-02T03:26:18.647 回答