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?
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?
If it does, you should make sure hitObjects is not marked as const. After all, that would be lying.
If not, it should take it by const World&. Then it's okay for hitObjects, which is marked const, to pass *this to it.
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.
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);
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*
Related
Today I got a problem. I am in the need of a static member function, const is not a must but a better. But, I didn't succeed in my efforts. Can anybody say why or how?
When you apply the const qualifier to a nonstatic member function, it affects the this pointer. For a const-qualified member function of class C, the this pointer is of type C const*, whereas for a member function that is not const-qualified, the this pointer is of type C*.
A static member function does not have a this pointer (such a function is not called on a particular instance of a class), so const qualification of a static member function doesn't make any sense.
I agree with your question, but unfortunately the C++ is designed that way. For example:
class A {
int i; //<--- accessed with 'this'
static int s; //<---- accessed without 'this'
public:
static void foo () const // <-- imaginary const
{}
};
As of today, the const is considered in context of this. In a way, it's narrow. It can be made broader by applying this const beyond this pointer.
i.e. the "proposed" const, which may also apply to static functions, will restrict the static members from any modification.
In the example code, if foo() can be made const, then in that function, A::s cannot be modified. I can't see any language side effects, if this rule is added to standard. On the contrary, it's amusing that why such rule doesn't exist!
It is unfortunate that C++ doesn't accept it as per design but logically there are few use cases in which it validates well.
A function which is class level valid(static) might not change any static data, may be it will just query data should be const.
May be it should be like
if(Object)
MakeThisConstant()
else
MakeStaticDataConstant() // Only in the scope but static data cannot be constant so may be it should in some scenarios
Without getting into the details, it's because there may or may not be an object modified by the function, so const is ambiguous to the compiler.
Recall that const keeps objects constant, but there may or may not be an object here to keep constant.
A 'const member function' is not
allowed to modify the object it is called on, but static member
functions are not called on any object.
It is used directly by scope resolution operator.
Thus having a const static member function makes no sense, hence it is illegal.
I'm trying to move an array to an other array (for initialize my datas structure).
My code:
void MonitorModule::setParameters(const std::array<std::string, IMonitorModule::MAX_CONTENT> ¶meters) const {
this->_parameters = parameters;
}
// Inside the structure "MonitorModule" as private
std::array<std::string, IMonitorModule::MAX_CONTENT> _parameters;
This is returning the following error:
error: no viable overloaded '='
How can I do this move of two std::array ?
Thanks.
setParameters() is qualified as const, which means it can only be called on a const MonitorModule object and thus its _parameters member cannot be modified. That is why the compiler cannot find a suitable operator= to assign another array to _parameters.
You need to drop the const qualifier from the declaration of setParameters().
The keyword const after method definition prevents modifying its members, so you should remove it or make _parameters mutable.
MonitorModule::setParameters is qualified const, meaning that it can't change object members.
Simply remove the const qualification.
I'm currently working on material from my data structures class, which involves an exercise where we attempt to define a class mimicking a vector so we can get an understanding of what's going on underneath the hood. Everything made sense until I realized that there are two definitions foroperator[]. In context:
typedef unsigned int size_type;
T& operator[] (size_type i) { return m_data[i]; }
const T& operator[] (size_type i) const { return m_data[i]; }
First question: why is it necessary to have two definitions of operator[]?
Second question: why doesn't this throw a multiple definitions error?
Sorry if anything is vague or seems obvious. I'm new to C++, my only other experience being in Java. Thanks!
This is a common C++ pattern.
The const member function (that is, the one with the keyword const after the prototype) applies when *this is const; in other words, if it is used with a const object. Since *this is const, it's reasonable to assume that it cannot be modified, so operator[] must return a const reference.
The other member function would apply to any object, but since it is less specific than the const one, it only applies if *this is not const. In that case, it is presumably possible to modify the returned reference (object[3] = new_value;), so the return type is not const.
First question: why is it necessary to have two definitions of
operator[]?
Those definitions differ with their const-qualifier (and result type). One of them is const and returns const reference to internal data. It is used if your container is declaread as const, so that reference to it's contents are const as well. If your contianer is not const, non-const operator is used so that internal data can be modified.
Second question: why doesn't this throw a multiple definitions error?
Because const-qualifier is a part of function prototype, which means that void foo(); and void foo() const; are actually two diffrent methods. It allows overloading based on const qualifier of object being used to call the method.
why is it necessary to have two definitions of operator[]?
It's necessary if you want one that you can modify its value (e.g. obj[i] = value) and the other cannot (with const).
why doesn't this throw a multiple definitions error?
Based on $9.3.1/3 states-
"A nonstatic member function may be declared const, volatile, or const volatile. These cvqualifiers affect the type of the this pointer (9.3.2). They also affect the function type (8.3.5) of the member function; a member function declared const is a const member function, a member function declared volatile is a volatile member function and a member function declared const volatile is a const volatile member function."
That said, you can overload a function by using one of those qualifiers, e.g.:
void func();
void func() const;
Each function can be recognized by what you can call signature, when you declare a function in C++ you write the signature of the function, a signature looks like
qualifiers T ( qualifiers U u ) qualifiers;
############ ------------------ ::::::::::
so the signature it's composed of the 2 part that I outlined with # and -, the part with # is the return type and the part - is the description for the arguments accepted by the function.
The point is that if you write the same signature with different qualifiers, C++ still considers this the re-declaration/re-definition of the same function, so qualifiers are part of the signature but when comparing multiple declarations/definitions of functions with the same name they are virtually dropped by your compiler.
You should read more about qualifiers, I simplified the concept here.
You can also add more qualifiers after the signature, the part I outlined with :, to declare some properties about the way your function works, for example const means that you declare that your function doesn't modify the variables that it can access .
Today I got a problem. I am in the need of a static member function, const is not a must but a better. But, I didn't succeed in my efforts. Can anybody say why or how?
When you apply the const qualifier to a nonstatic member function, it affects the this pointer. For a const-qualified member function of class C, the this pointer is of type C const*, whereas for a member function that is not const-qualified, the this pointer is of type C*.
A static member function does not have a this pointer (such a function is not called on a particular instance of a class), so const qualification of a static member function doesn't make any sense.
I agree with your question, but unfortunately the C++ is designed that way. For example:
class A {
int i; //<--- accessed with 'this'
static int s; //<---- accessed without 'this'
public:
static void foo () const // <-- imaginary const
{}
};
As of today, the const is considered in context of this. In a way, it's narrow. It can be made broader by applying this const beyond this pointer.
i.e. the "proposed" const, which may also apply to static functions, will restrict the static members from any modification.
In the example code, if foo() can be made const, then in that function, A::s cannot be modified. I can't see any language side effects, if this rule is added to standard. On the contrary, it's amusing that why such rule doesn't exist!
It is unfortunate that C++ doesn't accept it as per design but logically there are few use cases in which it validates well.
A function which is class level valid(static) might not change any static data, may be it will just query data should be const.
May be it should be like
if(Object)
MakeThisConstant()
else
MakeStaticDataConstant() // Only in the scope but static data cannot be constant so may be it should in some scenarios
Without getting into the details, it's because there may or may not be an object modified by the function, so const is ambiguous to the compiler.
Recall that const keeps objects constant, but there may or may not be an object here to keep constant.
A 'const member function' is not
allowed to modify the object it is called on, but static member
functions are not called on any object.
It is used directly by scope resolution operator.
Thus having a const static member function makes no sense, hence it is illegal.
I am reading some C++ text from the address https://cs.senecac.on.ca/~chris.szalwinski/archives/btp200.081/content/overl.html.
in the first lines, they say:
The signature of a member function consists of:
the function name,
the data types of its parameters,
the order of the parameters and
possibly
the const status of the function.
I don't understand what they mean by saying "the const status of the function".
Can anyone elaborate on that, please?
Thanks.
In C++, you can declare a member function of a class to be const, by appending that keyword to its signature (for instance, int MyClass:doSomething(int param) const {...}). Doing so guarantees that the function won't change the (non-mutable) members of the class object on which the function is called - and hence it can be called with const instances of that class.
It is permissible to have two different member functions for a class whose signature differs only in whether they are declared const or not.
They mean to sum up the items of where functions must differ in order to be put into the same class scope. The const at the end is:
struct A {
void f();
void f() const;
};
These are valid overloads. The first is called if you call f on a A, and the second is used if you call it on a const A:
A a;
a.f(); // takes first
A const& b = a;
b.f(); // takes second
Note that the term "signature" is misused here. The signature of a function is more broad, and includes also the class of which a function is a member of. A signature uniquely identifies a function.
Declaring a member function as const tells the compiler that the member function will not modify the object's data and will not invoke other member functions that are not const.
The compiler will check to make sure that you really don't modify the data. You can call a const member function for either a const or a non-const object, but you can't call a non-const member function for a const object (because it could modify the object).
You can read more about constness in C++ here.