2013-04-23 2 views
1

У меня есть этот простой классКак это «это» указатель используется в качестве аргумента функции члена

class foo { 
public: 
    void func() const; 
    void func2(); 
}; 

void foo::func() const {} 
void foo::func2() {} 

int main() { 
    const foo f; 
    f.func(); 
    f.func2(); 
} 

При попытке компиляции я получаю сообщение:

error: passing ‘const foo’ as ‘this’ argument of ‘void foo::func2()’ discards qualifiers [-fpermissive]

Я понимаю, использование не-const-члена объекта const, мой вопрос в том, как это «этот» указатель, используемый в качестве аргумента для func2?

+0

Измените 'const foo f;' на 'foo f' и" f.func2() "должно компилироваться в порядке. В противном случае изменение функции func2() на "const" также должно устранить проблему. В любом случае * любое * время, когда вы вызываете метод объекта, вы передаете «этот» указатель. Поскольку вы объявили объект f "const", а поскольку func2() не const ... компилятор жалуется. – paulsm4

ответ

2

Вы не можете вызвать функцию non-const func2 на объект const f.

Поскольку ваш вопрос:

how is the this pointer used as an argument to func2

вот некоторая информация цитировал IBM C++ documentation: this pointer:

The keyword this identifies a special type of pointer. Suppose that you create an object named x of class A , and class A has a nonstatic member function f() . If you call the function x.f() , the keyword this in the body of f() stores the address of x . You cannot declare the this pointer or make assignments to it.

A static member function does not have a this pointer.

The type of the this pointer for a member function of a class type X , is X* const . If the member function is declared with the const qualifier, the type of the this pointer for that member function for class X , is const X* const .

A const this pointer can by used only with const member functions . Data members of the class will be constant within that function. The function is still able to change the value, but requires a const_cast to do so:

void foo::p() const{  
    member = 1;      // illegal  
    const_cast <int&> (member) = 1; // a bad practice but legal 
} 

A better technique would be to declare member mutable

.

7

void foo::func2() не const, что означает, что он может изменить объект. Таким образом, компилятор не позволяет вызывать его для объекта const. Даже если вы ничего не измените в реализации func2. this - неявный аргумент для любой нестатической функции-члена. Вот как он знает, какой именно объект он призвал.

9.3.2 этот указатель [class.this]

1 In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called.

+0

Да, у меня есть эта часть. Меня интересует то, что сообщение компилятора ссылается на «этот» указатель как аргумент func2. Я пытаюсь понять, что это значит. Является ли это «неявным аргументом» для функции-члена? –

+0

@RichardJohnson 'this' является неявным аргументом для любой нестатической функции-члена. Вот как он знает, какой именно объект он вызвал для – alexrider

0

ваша функция член func2() должна быть константной. см. here.

3

Аргумент экземпляра для функций-членов - неявный. То есть, он никогда не является частью объявления функции, но тем не менее он там.

Помните, что (нестатические) функции-члены не являются функциями. Вы не можете просто позвонить им. Вместо этого вы всегда должны вызывать их на объекте . Этот экземпляр-объект неявно является аргументом функции-члена, но никогда не излагался. Он доступен внутри функции через выражение this.

Если аргумент неявного экземпляра привязывается к постоянному объекту, то тип this равен T const *, и могут быть вызваны только функции-члены, которые имеют значение const. Аналогично для volatile, и существует аналогичное правило для привязки неявного аргумента экземпляра к ссылке rvalue.

1

В ООП (как правило) все методы экземпляра молча преобразуются в статические функции компилятором, а указатель на структуру, которая создает состояние экземпляра (например, this), добавляется как скрытый первый параметр.

Так что:

class Foo 
{ 
    private: 
     Int32 _bar; 

    public: 
     void Add(Int32 x) 
     { 
      this->_bar += x; 
     } 
}; 

void Main() 
{ 
    Foo foo; 
    foo.Add(3); 
} 

фактически реализована следующим образом:

struct Foo { 
    Int32 _bar; 
} 

static void Foo_Add(Foo *thisPtr, Int32 x) 
{ 
    thisPtr->_bar += x; 
} 

void Main() 
{ 
    Foo foo; 
    Foo_Add(&foo, 3); 
} 
+0

Таким образом, ошибка на самом деле просто простое несоответствие типов, поскольку не допускается неявно преобразовывать объект const в объект, не являющийся объектом const. –

4

Вы видите артефакт на путь C++ определен. Функции-члены автоматически добавляют к каждой функции скрытый параметр this. Если объект равен const, то указатель также равен const, а функция-не-член-член должна получить указатель неконстантного this.

+1

Незначительное разъяснение только для записи - функции члена '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'не делают. – twalberg

+0

@twalberg, конечно, я должен был упомянуть об этом. Благодарю. –

0

В текущем коде как на компьютере есть код func2, которому нужно знать, в каком экземпляре foo посмотреть/в чем дело. Поэтому он передается в экземпляр указателя (this).

Смежные вопросы