The difference between static_cast <const A> (* this) and static_cast <const A &> (* this)

in the following code (taken from efficient C ++):

class A 
{
  ....
  char& operator[](std::size_t position)         // now just calls const op[]
  {
    return
      const_cast<char&>(           // cast away const on op[] return type;
        static_cast<const TextBlock&>(*this)   // add const to *this type;
          [position]                           // call const version of op[]
      );
  }

  const char& operator[](int index) const
  {
     ...
  }
}
//complete example, tested with VC 2010
#include<iostream>
#include<string>

class TextBlock
{
public:
    TextBlock(std::string st):text(st){};
    TextBlock(char* cstr): text(cstr){};
    TextBlock(const TextBlock& r)
    {
        std::cout<<"copy constructor called"<<std::endl;
    }
    char& operator[](int index)
    {
        std::cout<<"non-const operator"<<std::endl;
        return const_cast<char&>(static_cast<const TextBlock>(*this)[index]);
    }

    const char& operator[](int index) const
    {
        std::cout<<"const operator"<<std::endl;
        return text[index];
    }

private:
    std::string text;
};

int main()
{
    TextBlock rt("hello");
    std::cout<<rt[0]<<std::endl;
}

In this code, if you change the static_cast from const TextBlock & to const TextBlock, this leads to a non-constant version of the [] operator, called recursively. Can anyone explain what the reason for this is (why const TextBlock leads to the fact that the const member statement does not work []).

+3
source share
5 answers

The reason is that

const A a();

and

A b();

- , CPP ; , ​​ const non-const .

cout << a[0] << endl;

,

cout << b[0] << endl;

. [] . , const, . :

char& operator[](std::size_t position)
{
     return const_cast <char &>( static_cast <const A &>(*this) [position] );
}

, const

char& operator[](std::size_t position)
{
     const A temp = *this;      //create a const object 
                                    //and assign current object to it
     ....
}

[] const obj

char& operator[](std::size_t position)
{
     const A temp = *this;      //create a const object 
                                    //and assign current object to it
     return temp[position];     // call an overloaded operator [] 
                                // of the const function
}

, [] const const char & char &. ,

char& operator[](std::size_t position)
{
     const A temp = *this;      //create a const object 
                                //and assign current object to it
     return const_cast <char &>( temp[position] );
 }

. : "

const A temp = *this;
return const_cast <char &> (temp[position]);

:

return const_cast <char &> ( static_cast <const A &> (*this)[position]);

? , temp - const, :

const A temp = *this;                                // implicit cast

const A temp = static_cast <const A &> (*this)        //explicit  

:

const A temp = const_cast <const A &> (*this) 

- :

return const_cast <char &> (static_cast <const A &>(*this)[position]);

-const ref char const-casted, []:)

return const_cast <char &> ((*this)[position]);

-const-; ( []), .

, .

+3

[],

, const, const const: const TextBlock a("Hello"); TextBlock b("World");

a[0] b[0], operator[]. - a[0] const:

const char &operator[](int) const;

a const, . , [], const const char&, , .

, - b[0] const:

char &operator[](int);

, . , char &, .


?

, const. non-const const.

, , const . static_cast<>. , b const TextBlock, const.

char &operator[](int index) , .

char & operator[](int position) { // const TextBlock tmp = *this; // return const_cast<char &>(tmp[position]); return const_cast<char &>( (static_cast<const TextBlock &>(*this))[position] ); }

static_cast<const TextBlock &>(*this) , TextBlock & to const TextBlock & *this.

, tmp. tmp[0] const, .

const , const char &. char &. const_cast<char &> const . char, .

, return :

const TextBlcok &tmp = *this; return const_cast<char &>tmp[position];

tmp - * this ( ). TextBlock & const TextBlock & , return .

& , , . . , tmp *this. , . , tmp, , , !

+2

, char, reko_t, - g++ 3.4.6.

...

static_cast<const TextBlock>(*this)

... , ...

const TextBlock temporary = *this;

... . . , ​​, undefined.

? ( , int, ).

#include <iostream>

struct A  
{ 

  char operator[](int position)         // now just calls const op[] 
  { 
    return 
        static_cast<const A>(*this)     // add const to *this type; 
          [position];                   // call const version of op[] 
  } 

  const char operator[](int index) const 
  { 
    return x_[index];
  } 

  char x_[10];
};

int main()
{
  A a;
  strcpy(a.x_, "hello!");
  const A& ca = a;
  std::cout << a[0] << ca[1] << a[2] << ca[3] << a[4] << ca[5] << '\n';
}
+1

char& operator[](std::size_t position) char& operator[](std::size_t position) const . "const" . - "" , - const . , , const- , const.

const A a;
char c = a[i]; // Calls the const version
A b;
char d = b[i]; // Calls the non-const version

(* this) [position] , , . , const .

EDIT: .. , , . - ? , .

EDIT2: , . a [i] → const cast (const A) → temp [position] → const cast → temp2 [position] → .....
, const (const A &), , .

... static_cast<const TextBlock>(*this)[position]; :

  • * const TextBlock
  • , const TextBlock (-, const TextBlock)
  • [] , , .
  • .
0
source

Your operators have different types of parameters

char & operator [] (position std :: size_t)
const char & operator [] (int index) const <- Should also be std :: size_t

This may be the solution you are looking for. Was there an example from the book for different parameters of different types? Remember that casting type works with return value.

char& operator[](std::size_t index)
{
  std::cout<<"non-const operator"<<std::endl;
  const TextBlock &  ref = *this;
  return const_cast<char&>(ref[index]);
}
0
source

Source: https://habr.com/ru/post/1766724/


All Articles