Const changing variable values - c++

I have a virtual get method that looks like this in the super class:
virtual double getPortagem() const;
double via_Ligacao::getPortagem() const
{
return 0;
}
And in their "child":
double getPortagem();
double auto_Estrada::getPortagem()
{
return portagem;
}
The thing that is bugging me is if I declare the child method as non const the results will be accoding to the values inserted but if I declare as a const method it will return me a memory position. Could you guys explain me this, please?

function overriding is not being done as you are making a new function in the child classes by declaring non const function which is not getting any match with the function in the superclass.

In C++11 you can use the keyword override to ensure that an intended override really is an override:
double auto_Estrada::getPortagem() override
{
return portagem;
}
Then you get a compilation error if it isn't an override, which this non-const function isn't (since it differs in const-ness from the base class method of the same name).
Instead of overriding the base class function this function shadows the base class function, so that if you call o.getPortagem() where o is const and of class auto_Estrada, the compiler won't find the base class const function, and complain.
In C++03 about the best you could do was to statically assert that the same named base class function could be called with the same arguments (it helped but wasn't guaranteed). Note that C++03 didn't have a static_assert. The usual way to do C++03 static asserts was via a typedef of an array, with negative size where you wanted a compile time error.
Regarding terminology,
what you call a "child class" is a derived class (C++ terminology) or subclass (more general computer science terminology, I believe originally from Smalltalk),
what you call "memory position" appears to be arbitrary bits in an uninitialized variable, interpreted as a floating point value, which is called an indeterminate value.
It's formally Undefined Behavior to use an indeterminate value, so anything can happen.

Related

Understand C++ const functions

I am new to c++ and im trying to write a simple c++ wrappers to integrate with this third party c++ library; which comes with bad documentation.
function to integrate with (this is all the documentation that came with this function):
virtual ImageCoord Raster::groundToImage(const XyzCoord & groundPt,
double desiredPrecision=0.001,
double* achievedPrecision=null) const
Text about function: This method converts the given groundPt (x,y,z in meters) to a returned image coordinate (line, sample in full image space pixels).
there is also some class documentation
Raster Class Ref
inherits from GeoModel
Public member functions:
virtual ImageCoord groundToImage (const XyzCoord &groundPt, double desiredPrecision=0.001, double *achievedPrecision=NULL) const =0
in my code i have:
//this is implemented correctly
const XyzCoord xyz(284971.17549099098, -126866.36533847413, 6350003.627515804)
double desiredPrecision = 0.000001;
double achievedPrecision = 0.0;
// not sure if this is what the documentation meant by "image coordinate" but it comes with the library
// ImageCoord(double line, double point)
ImageCoord imagePoints;
// the part im confused about, what is the proper way to invoke the above function, the below line was me trying out how to call the method
const Raster::groundToImage(&xyz, imagePoints);
Sorry for my ignorance in c++ but I've been baffled. I have lot of programing experience (8 plus years, just none with c++ so i understand programing terms, concepts and design patterns).
Im also trying to understand in the function defination what does this mean
const XyzCoord & groundPt
I was able to compile with
XyzCoord xyz(204971.17549099098, -106866.36533847413, 6350003.627515804);
Raster* service;
ImageCoord imagePoints = service->groundToImage(xyz); //segmentation error occurs on this line
but i then get a runtime error "Segmentation fault"
This is a non-static member function of a class named Raster.
You are supposed to invoke it via member access obj.groundToImage(/*args*/) where obj is an object of the class type to which the function belongs or a class type derived from that class.
Or, if the call happens inside another non-static member function of the same class or a derived class, it could just be groundToImage(/*args*/) which will call the function implicitly on the current object.
With virtual it may also be possible to invoke the function on an object of a base class of Raster, depending on where the virtual function has been declared first in the class hierarchy.
There are certain more specialized situations where a qualified call replacing groundToImage with Raster::groundToImage in either of the above could also be the intended behavior.
The const qualification of the function is irrelevant. It just means that the function can be called whether obj is const-qualified or not. Similarly the const-qualification on the function parameter is irrelevant. It just means that you can pass either a const- or non-const-qualified first argument. You don't have to make xyz const to be able to pass it. Only the other way around, passing a const-qualified expression to a non-const reference parameter is a problem. const is intended to signal that the function will not modify the argument and therefore doesn't care whether or not it is const-qualified.
const only makes sense when used in a declaration or type. Something like
const Raster::groundToImage(&ecef, imagePoints)
as a supposed function call doesn't make syntactical sense.
The function also expects up to three arguments of the specified types and returns a ImageCoord. You are not supposed to pass one as an argument. It is what the function returns.
The arguments should probably be xyz, desiredPrecision and &achievedPrecision given that you already declared them with the correct types.
It probably wants the last one as pointer because it is an out-parameter.
What the object on which the member function is called on is supposed to be is unclear from what you have shown. We don't know what ecef is though...
TL;DR:
ImageCoord imagePoint = someRasterObject.groundToImage(
xyz,
desiredPrecision,
&achivedPrecision
);
Or
ImageCoord imagePoint = somePointerToRasterObject->groundToImage(
xyz,
desiredPrecision,
&achivedPrecision
);
From the signature given:
virtual // A derived class's implementation of
// this function can be called via a
// pointer or reference to a parent
// class object
ImageCoord // This function returns an ImageCoord
// object
Raster:: // This is a member of the Raster class
groundToImage( // This function is named groundToImage
const XyzCoord & groundPt, // The first argument to this function is a
// reference to a constant XyzCoord
// object
double desiredPrecision=0.001, // The second argument is a double with a
// default value of 0.001 if not provided
double* achievedPrecision=null // The third argument is a pointer to a
// double with a default value of null if
// not provided
)
const // This function can be called on a
// constant Raster object
That means you need 2-4 things to call this function:
A (possibly const-qualified) Raster object to call the function on
An XyzCoord object to pass as the first parameter
(Optional) A double to pass as the second parameter
(Optional) A pointer to a double to pass as the third parameter
While nothing in your question explicitly states it, I would assume the function uses the 3rd parameter as an output. I would assume it writes the actually achieved precision to the double pointed to by the pointer you pass it, so you'll probably want to just pass it the address of a local double variable.
Each non-static method in a class is called on behalf of some object of that class (or some derived class), and the object is accessible within a method by an implicitly defined this pointer.
The const qualifier appended after the parameters' list of the method applies to that this value. In other words, it declares this of a type classname const* instead of classname*.
As a result the compiler will reject any attempts to modify the *this object from within the const-qualified method, so the method can be safely used on non-modifiable objects.
For example, the length() method of the std::string class is declared as
size_t length() const;
so when you use it like, say:
std:string s;
....
size_t len = s.length();
you can be sure the s variable will not be modified during calculation of len value.

Non virtual pointer in c++?

Is it possible to have a “non virtual pointer” in c++ ( ie a pointer that calls the methods directly without dynamic dispatch). This is because I am trying to do something like this:
template <typename T>
class Ref {
T* value; // I am 100% sure that value points to an actual T object.
/* constructors and stuff */
auto operator -> () {
return value;
}
};
But this will unnecessarily call virtual functions when I know the dynamic type of value to be T...
I know that the user could enforce the usage of non-virtual functions like so:
X->Base::foo();
But that seems like another burden for the user. How can this be done automatically?
when I know the dynamic type of value to be T
You may know/assume this, but at present, there is no mechanism in C++ that can make the language know/assume this for any given pointer/reference to an object. If it is of a polymorphic type, then calling any virtual function (unless the caller explicitly specifies otherwise) will use dynamic dispatch.
Say your class T marks its virtual functions with final, the function calls should be devirtualized on all modern compilers.
See: https://quuxplusone.github.io/blog/2021/02/15/devirtualization/

static and dynamic resolution in C++

The text I'm following says:
A call to a virtual function using an object is always resolved statically. You only get a dynamic resolution through a pointer or a reference.
Now consider the following program:
#include <iostream>
class Mainclass{
protected:
double length{1.0};
double width{1.0};
double height{1.0};
public:
Mainclass(double lv, double wv, double hv):length{lv}, width{wv}, height{hv}{
std::cout<<"Three args box ran"<<std::endl;
}
void showVolume() const{
std::cout<<"Mainclass usable volume is: "<<Volume()<<std::endl;
}
virtual double Volume() const{
return length*width*height;
}
};
class Derivedclass: public Mainclass{
public:
Derivedclass(double lv, double wv, double hv): Mainclass{lv, wv, hv}{}
double Volume() const{
return 0.85*length*width*height;
}
};
int main(){
Mainclass first{20.0, 30.0, 40.0};
Derivedclass second {20.0, 30.0, 40.0};
first.showVolume();
second.showVolume();
}
Output:
Three args box ran
Three args box ran
Mainclass usable volume is: 24000
Mainclass usable volume is: 20400
Here, I'm calling the base class and the derived class objects via their object instances and not through a pointer. But it appears that the function is being resolved dynamically. Was the text wrong? If not what did it mean?
"A call to a virtual function using an object is always resolved statically. You only get a dynamic resolution through a pointer or a reference."
This sentence isn't so much describing a rule of the C++ language as a shortcut compilers are allowed to take.
You are calling showFunction directly on the names of objects. So suppose showFunction were declared virtual. The compiler knows the exact types of the objects called first and second: there's no way they could actually be objects of some other type. So although the language says any overriding function must be called by first.showVolume() and second.showVolume(), there's no possible way the result will be any functions other than the ones the compiler can find immediately, so it doesn't actually need to put any code for determining which function to call in the resulting program. The correct function Mainclass::showVolume() (or Derivedclass::showVolume(), if it existed), can be called directly, which can be slightly more efficient.
The quote doesn't apply to the call of Volume() inside showVolume(). Since Volume names a non-static member, Volume() means the same as this->Volume(). this is a pointer, which might or might not point at an object whose complete type matches the type Mainclass* const of the pointer. So in this case, the compiler is required to do dynamic resolution to determine which function to call.
But one more thing to note: it's true you can only get dynamic resolution through a pointer or reference, but it's not true you always get dynamic resolution through a pointer or reference. When a function is named as a "qualified id" using the :: token, the language says the function called is determined statically, and overrides are ignored. For example, if your code in showVolume() changed to use either Mainclass::Volume() or this->Mainclass::Volume(), you would see that it never calls Derivedclass::Volume.

C++: "unresolved overload function type" between classes

This is probably something elementary, I have a function from one class (called cell) with identifier woo_func_ptr taking a pointer to function of type void with no arguments (void (*void_ptr)(void)) (which I typedef). In another class, I have an object of cell and I use the method woo_func_ptr. It won't allow me to, I get the error in the above title. If these two functions were not embedded inside a class, they would work fine
typedef void (*void_ptr)(void);
double WOO{0};
struct cell {
void woo_func_ptr(void_ptr jo)
{
jo();
}
};
class woosah
{
public:
void woo_func()
{
WOO+=rand();
std::cout << WOO << std::endl;
};
void run()
{
// other stuff
temp_cell.woo_func_ptr(woo_func);
// yet more stuff
}
cell temp_cell;
};
First of all pointer to woosah member function should be declared as
typedef void (woosah::*void_ptr)(void);
and then compiler would complain that it needs to see woosah definition while parsing this statement.
If you let compiler parse class woosah first by moving it up then it will complain that type cell is not defined (since it is contained within woosah). That wil still not solve your problem because of cyclic dependency while parsing.
One way is to solve cyclic dependency is by making temp_cell a pointer to cell instance and have it contained within woosah.
Also note, the syntax to call member function is by using .* or ->*
void run()
{
// other stuff
temp_cell->woo_func_ptr(temp_cell->*woo_func); // assuming temp_cell is pointer to some cell instance
// yet more stuff
}
http://msdn.microsoft.com/en-us/library/b0x1aatf(v=vs.80).aspx shows similar errors and their fixes.
A member function is not like a regular function. That's why there's a seperate "pointer to member function" type. It's because member functions are passed the implicit this pointer.
In fact, the standard even limits (severly) the casting of pointer to member function.
That's the source of your error.
You could use a static class function...
Change
void woo_func()
to
static void woo_func()
This will of coarse may not be what you want if you are trying to access data members of a particular object.
Member functions are kind of special and should not be treated as normal functions.

Using 'const' in class's functions [duplicate]

This question already has answers here:
Meaning of 'const' last in a function declaration of a class?
(12 answers)
Closed 5 years ago.
I've seen a lot of uses of the const keyword put after functions in classes, so i wanted to know what was it about. I read up smth at here: http://duramecho.com/ComputerInformation/WhyHowCppConst.html .
It says that const is used because the function "can attempt to alter any member variables in the object" . If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way.
class Class2
{ void Method1() const;
int MemberVariable1;}
So, what is the real definition and use of const ?
A const method can be called on a const object:
class CL2
{
public:
void const_method() const;
void method();
private:
int x;
};
const CL2 co;
CL2 o;
co.const_method(); // legal
co.method(); // illegal, can't call regular method on const object
o.const_method(); // legal, can call const method on a regulard object
o.method(); // legal
Furthermore, it also tells the compiler that the const method should not be changing the state of the object and will catch those problems:
void CL2::const_method() const
{
x = 3; // illegal, can't modify a member in a const object
}
There is an exception to the above rule by using the mutable modifier, but you should first get good at const correctness before you venture into that territory.
Others have answered the technical side of your question about const member functions, but there is a bigger picture here -- and that is the idea of const correctness.
Long story short, const correctness is about clarifying and enforcing the semantics of your code. Take a simple example. Look at this function declaration:
bool DoTheThing(char* message);
Suppose someone else wrote this function and you need to call it. Do you know what DoTheThing() does to your char buffer? Maybe it just logs the message to a file, or maybe it changes the string. You can't tell what the semantics of the call are by just looking at the function declaration. If the function doesn't modify the string, then the declaration is const incorrect.
There's practical value to making your functions const correct, too. Namely, depending on the context of the call, you might not be able to call const-incorrect functions without some trickery. For example, assume that you know that DoTheThing() doesn't modify the contents of the string passed to it, and you have this code:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(msg.c_str());
}
The above code won't compile because msg.c_str() returns a const char*. In order to get this code to compile, you would have to do something like this:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(msg.begin());
}
...or even worse:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(const_cast<char*>(msg.c_str()));
}
neither of which, arguably, are 'better' than the original code. But because DoTheThing() was written in a const-incorrect way, you have to bend your code around it.
The meaning is that you guarantee to clients calling a const function member that the state of the object will not change. So when you say a member function is const it means that you do not change any of the objects member variables during the function call.
const, when attached to a non-static class method, tells the compiler that your function doesn't modify the internal state of the object.
This is useful in two ways:
If you do write code that changes internal state in your const method, the compiler catches the error, moving a programming error from run-time to compile-time.
If client code calls a non-const method on a constant pointer, the compiler catches the error, ensuring the "chain of not changing things" is maintained.
Typically you want to declare all non-mutating non-static class methods as const. This allows calling code to use the const qualifier on pointers, and it helps catch mistakes.
Typical C++: you can declare a class member variable "mutable" and then change it even from a const method.
The const keyword used after a method indicate that this method doesn't modify the object on which it's called. This way, this method can be called on a const version of the object.
If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way?
Well, no. Sometimes you do want instance methods to modify members. For example, any set method will obviously need to set variables, so it's not the case that you should put const everywhere. But if your object's state is totally immutable, first consider whether it might not be better to have no instances at all (i.e., a static class), and if that's not the case, then make everything const.
It's quite unusual not to want to have any member variables changed, but if that's what your class requires, then you should make all your member functions const.
However, you probably do want to change at least some members:
class A {
private:
int val;
public:
A() : val(0) {}
void Inc() { val++; }
int GetVal() const { return val; };
};
Now if I create two instances of A:
A a1;
const A a2;
I can say:
a1.GetVal();
a2.GetVal();
but I can only say:
a1.Inc();
trying to change the value of a constant object:
a2.Inc();
gives a compilation error.