8

如果我这样做:

// In header 
class Foo {
void foo(bar*);
};

// In cpp
void Foo::foo(bar* const pBar) {
//Stuff
}

编译器不会抱怨 Foo::foo 的签名不匹配。但是,如果我有:

void foo(const bar*); //In header
void Foo::foo(bar*) {} //In cpp

代码将无法编译。

到底是怎么回事?我正在使用 gcc 4.1.x

4

7 回答 7

15

首先,您已向编译器(而非该类的其他用户)承诺您不会编辑该变量。

在您的第二个示例中,您已向该类的其他用户承诺您不会编辑他们的变量,但未能遵守该承诺。

我还应该注意,两者之间存在明显差异

bar* const variable

const bar* variable

const bar* const variable

在第一种形式中,指针永远不会改变,但您可以编辑指向的对象。在第二种形式中,您可以编辑指针(将其指向另一个对象),但不能编辑它指向的变量。在最终形式中,您既不会编辑指针,也不会编辑它指向的对象。参考

要对所述问题进行更多说明,您始终可以承诺 MORE const 多于 less。给定一个类:

class Foo {
    void func1 (int x);
    void func2 (int *x);
}

您可以编译以下实现:

Foo::func1(const int x) {}
Foo::func2(const int *x) {}

或者:

Foo::func1(const int x) {}
Foo::func2(const int* const x) {}

没有任何问题。您已经告诉您的用户您可能会编辑他们的变量。在你的实现中,你告诉编译器这个特定的实现不会编辑这些变量,即使你告诉用户你可以。您没有违反对用户的承诺,因此代码可以编译。

于 2008-11-06T19:07:02.183 回答
6

看到这个问题这个问题,还有这个问题

基本上, const 仅表示该函数不会修改指针的值。指针内容不是 const,与标头的签名相同。

于 2008-11-06T19:08:55.037 回答
2

第一个示例中的const关键字没有意义。你是说你不打算改变指针。但是,指针是按值传递的,因此更改与否无关紧要;它不会影响调用者。同样,您也可以这样做:

// In header 
class Foo {
void foo( int b );
};

// In cpp
void Foo::foo( const int b ) {
//Stuff
}

你甚至可以这样做:

// In header 
class Foo {
void foo( const int b );
};

// In cpp
void Foo::foo( int b ) {
//Stuff
}

由于int是按值传递的,因此常量无关紧要。

在第二个示例中,您说您的函数采用指向一种类型的指针,但随后将其实现为采用指向另一种类型的指针,因此它失败了。

于 2008-11-06T19:22:20.873 回答
0

在前者中,const不影响接口,只影响实现。你是在对编译器说,“我不会bar*在这个函数中改变值”。您仍然可以更改指针指向的内容。在后者中,您告诉编译器(和所有调用者)您不会更改指向bar的结构。bar*

于 2008-11-06T19:07:16.350 回答
0

所以第二个常量在:

void Foo::foo(const bar* const);

不是方法签名的一部分?

于 2008-11-06T19:13:44.200 回答
0

使用指针以外的变量类型更容易理解。例如,您可以有以下函数声明:

void foo( int i );

定义可能如下所示:

void foo( const int i ) { ... }

变量“i”在定义端是否为 const 是一个实现细节。它对该功能的客户没有影响。

于 2008-11-06T19:33:30.650 回答
0

它可能不太在意,void Foo::foo(bar* const pBar)因为您如何对待指针本身(是否为 const)在例程之外一点都不重要。C 规则说,对 pBar 的任何更改都不会在 foo 之外传播。

但是,如果是(const bar* pBar),那会有所不同,因为这意味着编译器不允许调用者传入指向非常量对象的指针。

于 2008-11-06T19:38:44.210 回答