0

I'm trying to initialize an instance of my class ShadeRec with its constructor:

ShadeRec(World& world);

So I pass to it:

ShadeRec sr(*this);

where "this" is an instance of the class World.

I get the following error:

World.cpp: In member function ‘ShadeRec World::hitObjects(const Ray&) const’:
World.cpp:52: error: no matching function for call to ‘ShadeRec::ShadeRec(const World&)’
ShadeRec.h:17: note: candidates are: ShadeRec::ShadeRec(const ShadeRec&)
ShadeRec.h:15: note:                 ShadeRec::ShadeRec(World&)

Assuming the problem is just that the World instance has the attribute const, how can I get rid of this error message?

LihO
  • 39,598
  • 10
  • 94
  • 164
  • 1
    Does the constructor need a non-const reference? If not, why not make it take a const reference? – us2012 Mar 25 '13 at 20:30
  • Highly similar to http://stackoverflow.com/questions/2912445/how-to-discard-const-in-c/2912726#2912726. Also look @ http://stackoverflow.com/questions/5598703/c-const-usage-explanation for pointers on how const works. – user2184879 Mar 25 '13 at 20:57

4 Answers4

7

You're doing this in the hitObjects member function which is marked as const. Think of it this way: that member function is promising not to modify the *this object. However, it's happily passing it to a different object by non-const reference. What if that other object modified it? Uh oh!

There are two possible solutions that depend on the problem. Does the ShadeRec constructor actually modify the passed World object?

  1. If it does, you should make sure hitObjects is not marked as const. After all, that would be lying.

  2. If not, it should take it by const World&. Then it's okay for hitObjects, which is marked const, to pass *this to it.

Joseph Mansfield
  • 104,685
  • 19
  • 232
  • 315
  • It doesnt modify the passed object, ShadeRec uses it to initialise ShadeRec instance's World object. But when I change the parameter to const World& I get an other error. ShadeRec.cpp: In constructor ‘ShadeRec::ShadeRec(const World&)’: ShadeRec.cpp:7: error: invalid initialization of reference of type ‘World&’ from expression of type ‘const World’ – Rupert Cobbe-Warburton Mar 25 '13 at 22:02
  • and now I get this: Undefined symbols for architecture x86_64: "Point3D::Point3D(Point3D const&)", referenced from: ShadeRec::ShadeRec(ShadeRec const&)in cclHIDes.o ShadeRec::ShadeRec(ShadeRec const&)in cclHIDes.o Ray::Ray(Ray const&)in cclHIDes.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status – Rupert Cobbe-Warburton Mar 25 '13 at 23:27
  • @RupertCobbe-Warburton I'll respond to your first comment first. You have a more fundemental problem. You are passing `*this` which is `const` to the new `ShadeRec` object which keeps a non-`const` reference of the object. That simply can't work. Why doesn't `ShadeRec` keep a `const` reference? Or maybe `hitObjects` shouldn't be a `const` member function. – Joseph Mansfield Mar 25 '13 at 23:31
  • @RupertCobbe-Warburton Second comment: That means you've declared a `Point3D` copy constructor but haven't defined it. – Joseph Mansfield Mar 25 '13 at 23:32
  • Yes, I had it wrong with the function. Now hitObjects is not const. Hence the second comment. – Rupert Cobbe-Warburton Mar 25 '13 at 23:33
  • What do the other 2 classes have to do with it? – Rupert Cobbe-Warburton Mar 25 '13 at 23:34
  • That was weird, I implemented Point3D 2 weeks ago and I forgot to complete one of the constructors but the error just came today..oh well, thanks a lot mate! – Rupert Cobbe-Warburton Mar 25 '13 at 23:37
0

There is a difference between a const reference and a non-constant.

The compiler doesn't want to pass a constant object to a method that takes a non-constant (mutable) object. That would violate interface agreements: being able to modify a constant object.

This situation may arise from a constant object calling mutable functions or a constant method calling mutable method.

Thomas Matthews
  • 54,980
  • 14
  • 94
  • 148
  • An object being passed using a const reference is not a constant object. The word `const` in a const reference is telling nothing about the object, it's just expressing a property of the reference. – 6502 Mar 25 '13 at 20:35
0

Type of this pointer within the const member function of a class World is const World*, which means that you can't use it to initialize a non-const reference (you can't just "drop" its constness).

Change the type of the argument of ShadeRec's constructor to const World&:

ShadeRec(const World& world);
See C++03, 9.3.2 §1:

The type of this in a member function of a class X is X*. If the member function is declared const, the type of this is const X*

LihO
  • 39,598
  • 10
  • 94
  • 164
  • It doesnt modify the passed object, ShadeRec uses it to initialise ShadeRec instance's World object. But when I change the parameter to const World& I get an other error. ShadeRec.cpp: In constructor ‘ShadeRec::ShadeRec(const World&)’: ShadeRec.cpp:7: error: invalid initialization of reference of type ‘World&’ from expression of type ‘const World’ – Rupert Cobbe-Warburton Mar 25 '13 at 23:07
0

Assuming you can construct a ShadeRec from a World without modifying the passed-in World, you need a ShadeRec constructor like this:

 ShadeRec(const World& world);
John Jesus
  • 2,174
  • 14
  • 17