2

Just a little warning: I've only been doing C++ for 2 weeks now, expect to see stupid beginner errors.

I was writing some (useless) code to get familiar with classes in C++ (it's a wrapper around a string), and I added a copy constructor, but I keep on getting this error:

pelsen@remus:~/Dropbox/Code/C++/class-exploration> make val
g++ -o val.o val.cpp
val.cpp: In copy constructor ‘CValue::CValue(const CValue&)’:
val.cpp:27: error: passing ‘const CValue’ as ‘this’ argument of ‘const std::string CValue::getData()’ discards qualifiers
make: *** [val] Error 1

I have done research, apparently this error is caused by the copy constructor doing non-const operations. I get that much. In response, I made CValue::getData() a const member. Apart from accessing getData(), the copy constructor doesn't do anything, so I don't see why I am still getting the error. Here is (some of) the buggy code:

  7 class CValue {
  8   string *value;
  9 public:
 10   CValue();
 11   CValue(string);
 12   CValue(const CValue& other);
 13   ~CValue();
 14   void setData(string);
 15   const string getData();
 16 };
 17 
 22 CValue::CValue(string data) {
 23   value = new string(data);
 24 }
 25 
 26 CValue::CValue(const CValue& other) {
 27   value = new string(other.getData());
 28 }
 37 
 38 const string CValue::getData() {
 39   return(*value);
 40 }

Does anyone know what I'm doing wrong? Cause I have no idea. Thanks in advance, and I guess I'm buying a proper C++ book to get started properly.

Greg S
  • 12,333
  • 2
  • 41
  • 48
xfbs
  • 177
  • 1
  • 1
  • 9
  • +1 for getting a proper book, I'd recommend [Accelerated C++](http://www.amazon.com/Accelerated-C-Practical-Programming-Example/dp/020170353X/ref=sr_1_1?ie=UTF8&qid=1309525070&sr=8-1) or have a look at the [book list](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Fabio Fracassi Jul 01 '11 at 12:59
  • @Fabio That's the book I was going to buy when I wrote the question :D. I picked it because it teaches programming by example (just like Dive into Python, the first programming book I read). Thanks for the recommendation :) – xfbs Jul 01 '11 at 13:05

2 Answers2

6

Instead of

const string getData();

try

string getData() const;

Your version makes the return string const, not the method.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • Thanks. But isn't it also smart to have the returning string be const? – xfbs Jul 01 '11 at 12:27
  • It depends on whether you want to change the string afterward. Note that the return string is not the same string in your class, but a copy of it, so modifying the return string will not change the string in your class. – Luchian Grigore Jul 01 '11 at 12:30
  • Right, it's a copy. I forgot about that. Another question: a copy is made automatically with the object's copy constructor when it's returned from a function, right? – xfbs Jul 01 '11 at 13:11
  • Yes, if that object does not have a copy constructor, the compiler uses a default one. – Luchian Grigore Jul 01 '11 at 13:39
  • Generally, yes, @Xfbs. However, there are certain situations where the compiler can detect that copying isn't necessary. In those cases, the value that gets returned inside the function is never used again, so the compiler decides to just keep using that instead of forcing a copy and then destroying the original. These cases are known as the *named return-value optimization* and *return-value optimization*, or (N)RVO. Don't rely on those optimizations being applied, but don't rely on the copy constructor being called in all cases, either. – Rob Kennedy Jul 01 '11 at 13:51
  • @Rob Got it :D. I used to do some coding in ruby, where all objects are returned by reference instead of copied. If I wanted that behavior, I'd have to return pointers :(. Thanks :) – xfbs Jul 01 '11 at 17:49
4

You need to make getData a const-method:

 const string CValue::getData() const {
     return *value;
 }

Also, as your class looks now, it is not necessary to make value a pointer. Just make it a member-object.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • Thanks a lot :D. I thought I already made the function CValue::getData() const. But okay, in C++ it seems to matter a lot where keywords are placed. I remember reading how to write a function that receives a reference to a const pointer to a const int or soemthing like that... I know, I could make value a member-object, but I wanted to also use this class to play around with std::auto_ptr (once I get the class working). Anyway, thanks a lot for the answer :D – xfbs Jul 01 '11 at 12:25
  • For reference, it helps to figure out declarations if you read them right-to-left. For example, your original was "method getData returning a string which is const" and the new one is "const method getData returning a string which is const". HTH – Useless Jul 01 '11 at 12:58
  • @Useless thanks for that hint - I guess I'm the more useless one here :p. What exactly does HTH mean tho? – xfbs Jul 01 '11 at 13:09
  • Oh, okay. It did help :). As soon as I'm familiar with writing classes in C++ I'll try to write some code that can work with 2x2 matrices. – xfbs Jul 01 '11 at 13:20