About "error: assignment of data-member ‘A::pCost’ in read-only structure"

About "error: assignment of data-member ‘A::pCost’ in read-only structure".

Hi there,

I got an error as above.

My requirements are: I need a derived class A from class B. In A, there are two member functions, i.e., Initialise() and GetCost(). The Initialise() initialises pointer pCost pointing to an array, and every invocation of GetCost() change the array pCost pointing to.

1. I know that a const function GetCost() can not change the value of the member variable, e.g., pCost. However, I think there is a way to use pointer to solve the problem but I don't know how to do it.

2. The GetCost() in class A is overriden from a virtual function in class B. Can I remove the 'const' after the function?

The codes are shown below, and any suggestions would be appreciated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Class A : public B
{
  public:  
   
  void Initialise(void);
  void GetCost( const CostType & cost ) const;
   
  protected:
  
  double* pCost;
};

void A::Initialise(void)
{
   
  double iniCost[12] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 };
  pCost = iniCost;
}

void GetCost( const CostType & cost ) const
{

  double updatedCost[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  updatedCost = cost; // error as well
   
  pCost = updatedCost; // error: assignment of data-member ‘A::pCost’
}
What is CostType in your code?
And you can not just assign a array to a pointer, what will work is:
1
2
3
4
5
6
7
8
void GetCost( const CostType & cost ) const
{

  double updatedCost[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  updatedCost = cost; // error as well
   
  pCost = &updatedCost[0]; // error: assignment of data-member ‘A::pCost’
}


But then the array 'updatedCost' will be deallocated at the and of your function and 'pCost' will be a dangling pointer, pointing to nothing. The proper way of doing this is:
1
2
3
4
5
6
7
8
9
10
11
12
void GetCost( const CostType & cost ) const
{

  double* updatedCost = new double[12];
  for (int i = 0; i < 12; i++)
  {
    updatedCost[i] = 0;
  }
  updatedCost = cost;
   
  pCost = updatedCost;
}


But then you need to add a destructor for you class to free up the memory:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
	

Class A : public B
{
  public:  
   
  void Initialise(void);
  void GetCost( const CostType & cost ) const;
  ~A();
  protected:
  
  double* pCost;
};
void A::Initialise(void)
{
   
  double iniCost[12] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 };
  pCost = iniCost;
}

void GetCost( const CostType & cost ) const
{

  double* updatedCost = new double[12];
  for (int i = 0; i < 12; i++)
  {
    updatedCost[i] = 0;
  }
  updatedCost = cost;
   
  pCost = updatedCost;
}
A::~A()
{
  delete [] this->pCost;
}


As for the error of 'updatedCost = cost;' if CostType has not cast to double*, you can't assign a CostType to a double*.
Last edited on
Thanks very much! Raggers!

Yes, your fast reply helps me a lot! I haven't got the compiler on this machine, but anyway, I think it should work now.

As you mentioned, here CostType is eventually type-defined as an array type.

Because I haven't test the modified codes, but one of my concern is that can we change the member varible 'pCost' here in a const member function GetCost()?

My understanding is that pCost is a pointer and we can change the value it points to in a const member function. If there is a normal member object we can't change it in the GetCost().

Another method is to define a 'mutable' member variable like:

1
2
3
4
5
6
7
8
9
10
11
Class A : public B
{
  public:  
   
  void Initialise(void);
  void GetCost( const CostType & cost ) const;
  ~A();
  protected:
  
  mutable double m_Cost[12];
};



1
2
3
4
5
6
7
8
9
10
11
12
13
void A::Initialise(void)
{
   
  double iniCost[12] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 };
  m_Cost = iniCost;
}

void GetCost( const CostType & cost ) const
{

  m_Cost = cost;

}


Will this work? Please point out if anything is inappropriate. Cheers!





I don't really understand your question but:

Making a const member functions will allow you to call the function from a const instance of the object:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Class A
{
  public:  
    void foo () const;
    void bar ();
};

int main ()
{
   const A myConst;
   A myNotConst;
   myConst.foo(); // this is oke.
   myConst.bar(); // here you will get a error saying you can't call a non-const function from a const object.
   myNotConst.foo(); // this is oke.
   myNotConst.bar(); // this is oke. const functions can be called from a non-const object.
}


Making a const member functions means it will not alter the object itself, this doesn't mean they can't, it's up to you to do so in your function. But this defeats the logic behind making const objects.

edit:
But this defeats the logic behind making const objects.

That's not fully true, but in your case it is. const has some other properties that are useful even if you const member functions edit the object itself.
Last edited on
Topic archived. No new replies allowed.