Square bracket overloading operator to set instead of get c++ - c++

For getting the value(i.e the function returns the value)
for ex -
if we do this in main.cpp
cout << Object[0] << endl;
it will print the first element of the object array.
and the function will look like this
double myArray::operator[](int index) const {
*//your code*
}
but what if we need to set the value what would be the prototype going to look like?
Let's say in main.cpp, we have
object[0] = 5;
Now this should set the first element as 5 we know that it shouldn't return anything!! so return_type is void!! but how we going to pass the index(i.e 0) and the RHS(Right hand side) value into the function?

Just declare two operators
const double & myArray::operator[](int index) const {
*//your code*
}
and
double & myArray::operator[](int index) {
*//your code*
}

Related

*this (Return reference to the calling object) does not return changed object's value in that function

Suppose there are two object : num1 , num2 each store integer number of 5 .
I want to add both object's value using non member function so result is : 10 .
But THE OUTPUT show value : 5 .
Is there any error in class member function or *this pointer ?
main.cpp
#include<iostream>
#include"Person.h"
using namespace std ;
int main(){
Person num1 ;
Person num2 ;
num1.InValueCapture(5) ;
num2.InValueCapture(5) ;
add(num1,num2); //non class member function : num1+num2 expecting result : 10
cout << "THE OUTPUT : " << num1.GetValueCapture() << endl; //but now we get 5
return 0 ;
}
Person.h
#ifndef PERSON.H
#define PERSON.H
struct Person{
private:
int value_capture ;
public:
int InValueCapture(int value){
value_capture = value ;
}
int GetValueCapture() const {
return value_capture ;
}
//adding two data
Person& combine(const Person &Rdata)
{
value_capture += Rdata.value_capture ;
std::cout << "value capture : " << value_capture <<std::endl; // use to check value inside DataSum.value_capture
return *this ;
}
};
Person add(const Person &Ldata , const Person &Rdata) //nonmember function
{
Person DataSum = Ldata;
DataSum.combine(Rdata); // add Rdata to Ldata , call class function combine
return DataSum ; //
}
#endif
Thank you for your guidance , appreciate your help .
Comments are liars:
DataSum.combine(Rdata); // add Rdata to Ldata , call class function combine
This does not "add Rdata to Ldata". You are calling a method of DataSum which is a copy of LData. Modifiying the copy has no effect on the original LData. Don't make a copy:
void add(Person &Ldata , const Person &Rdata) //nonmember function
{
Ldata.combine(Rdata); // add Rdata to Ldata , call class function combine
}
Actually I am not 100% sure what the function is supposed to do. If you want to modify the first parameter you cannot pass it as const reference. If you want to not modify it passing const reference is fine, then you can return the result, but thats already what your function does, just that you ignore the returned value. I removed the return to make it more clear that the function modifies its first parameter. Though, now the caller can as well call combine directly.
Change
Person add(const Person &Ldata , const Person &Rdata)
to
[[nodiscard]] Person add(const Person &Ldata , const Person &Rdata)
add is a "pure" function, in that it returns the sum of L and R.
It does not modify either.
Once you do this:
add(num1,num2); //non class member function : num1+num2 expecting result : 10
this results in a compiler error, as you are doing the equivalent of x+y then discarding the result.
num1 = add(num1, num2);
does what you want.
A function called add should not modify its arguments.
Possibly you should embrace operations. Change combine to:
//adding two data
Person& operator+=(const Person &Rdata)&
{
value_capture += Rdata.value_capture ;
std::cout << "value capture : " << value_capture <<std::endl; // use to check value inside DataSum.value_capture
return *this ;
}
and add to:
// notice we take Ldata **by value**, making a copy
[[nodiscard]] Person operator+(Person Ldata, const Person &Rdata) {
Ldata += Rdata;
return Ldata;
}
your main code then becomes:
num1 = num1+num2;
or
num1 += num2;
both of which are very clear in what they should do.

(C++) Cannot use string::substr to assign substrings to objects

I am designing a cheat for the game WordBrain. Basically this is just a small program that takes a number of letters, permutes the sequence, then splits the sequence into 'words' which have length attribute, then search my text file to file meaningful permutation to print out.
while (next_permutation(letters.begin(), letters.end())) //loop through possible permutations of the combination
{
int position_marker = 0; //serve specific purpose
for (auto x : substring_collection) //trouble is in this loop
{
string temp;
int k = x.take_length();
try { temp = letters.substr(position_marker, k); }
catch (out_of_range) { cout << "OUT OF RANGE"; }
x.set(temp); //member content does not register change
position_marker += x.take_length(); //also member word_length is 0 now, despite their are no invocation of methods capable of changing it
}
if (all_of(substring_collection.begin(), substring_collection.end(), [&](substring & s) {return !(library.find(s.take_content()) == library.end()); }))
{
for (auto x : substring_collection)
{
cout << x.take_content() + " ";
}
}
}
This is the location the trouble stems from. Basically, substring_collection is a vector<substring>, which contains objects of class substring
Here is how the class looks like:
class substring
{
private:
std::string content;
int word_length;
public:
substring() : content(""), word_length(0) {};
substring(std::string & s, int c) : content(s), word_length(c) {};
void set(std::string & s)
{
content = s;
}
void clear()
{
content.clear();
}
void set_length(int c)
{
word_length = c;
}
void showinfo() const
{
std::cout << "Content is " + content << " Length is : " << word_length;
}
int take_length() const
{
return word_length;
}
std::string take_content() const
{
return content;
}
};
I suspect that the reason the code goes wrong is position_marker, whose value depends on the member 'word_length' of the object substring is set to 0.
In the code prior to this loop, I only the setting method for this member to take data from users' input (from std::cin).
Can you please tell me that is there any hidden mechanism that reset the property, or create brand new objects that I did not aware of?
Also, teachings on coding styles are very welcomed. I just started learning to code so any tips are much appreciated.
for (auto x : substring_collection)
Here, x is of type substring. This is a copy of the element in the vector, and then when you modify it, you only modify the copy, not the original.
You'll have to use a reference to modify the original element in the vector
for (auto& x : substring_collection)
For why word_length is 0, I don't know, it isn't in the code you posted. My guess would be that you resized the vector, which called the default constructor of substring, which set word_length to 0.

C++ : how to return the value from an out of bounds array with exception handling?

I am having trouble returning the value of an out of bounds array using an exception formalism.
I create an array object in my main script with for example length 10 using a class Array. Than I try to set the 11th element of the array to a certain value. In my class Array I throw back a value from a class ArrayOutOfBounds when the index of an array is larger than the size of the array, which is true in this case. In my main script I than catch this object from the ArrayOutofBounds class to give the out of bounds index and a terminal message that states that the array is out of bounds. However, how do I return the actual value I was trying to set the 11th element to?
It looks as follows:
class ArrayOutOfBounds + overloading operator << function
class ArrayOutOfBounds {
public:
ArrayOutOfBounds(int index) : _index(index) {} ;
int index() const { return _index ; }
private:
int _index ;
} ;
ostream& operator<<(ostream& os,const ArrayOutOfBounds& m) {
return (os << "Array index is out of bounds") ;
}
Throw back function within class Array:
double& operator[](int index) {
if(index > _size) {
ArrayOutOfBounds aoob(index) ;
throw aoob ;
}
return _arr[index] ;
Main script:
int main() {
Array array(10) ;
try {
array[11] = 10 ;
}
catch(ArrayOutOfBounds aoob) {
cout << '\n' ;
cout << aoob << " (index, value): " << aoob.index() << ", " << 10 << endl ;
}
cout << '\n' ;
return 0 ;
}
I tried to add a second throw value that throws _arr[index] but I understood you can't throw two things at once.
However, how do I return the actual value I was trying to set the 11th element to?
You are not setting anything with the function. Since the function returns a reference your class has no idea what the caller is doing with it. It could be setting a value, making a copy, passing it to a function, it just can't know. If you need to know then you need to rewrite the operator to overload the function operator () and then you can take in the index and the value you want to set at the index.
You can then modify the ArrayOutOfBounds to take in two parameters. The index and the value and then you can access them inside the catch block.
It is not possible with the operator[] as it is currently written because the exception is thrown before there is any attempt to assign a value to the reference.
Instead of using operator[] you could write a different member function to set values that takes two parameters, an index and a value:
void setAt(int index, double value) {
if (index < 0 || index >= values.size())
throw ArrayOutOfBounds{index, value};
values[index] = value;
}
Live demo.
You could change operator[] so that it returns a proxy object that can be in an "out-of-bounds" state and then only when you try and assign a value to that proxy object is the exception thrown:
ArrayElementProxy operator[](int index) {
return ArrayElementProxy{*this, index};
}
class ArrayElementProxy {
Array* array_;
int index_;
public:
ArrayElementProxy(Array& array, int index) : array_(&array), index_(index){}
Array& operator=(double value){
array_->setAt(index_, value);
return *array_;
}
operator double() const{
return array_->getAt(index_);
}
};
Live demo.
But I think proxy objects are generally best avoided (just ask anyone who has tried to use vector<bool>).

Having issues with overloading C++ operators

I'm having some issues understanding this concept. In the main.cpp file, we have a function as follows:
void TestComparison()
{
MyFloat X, Y;
cout << "\n\n============ Testing \"==\" for MyFloat ================\n";
do
{
cout << "\nEnter X ==> ";
X.Read();
cin.ignore(1000, '\n'); // Discard all chars in input stream.
cout << "\nEnter Y ==> ";
Y.Read();
cin.ignore(1000, '\n'); // Discard all chars in input stream.
cout << "\n\n";
if ( X == Y )
{
X.Write(); cout << " is equal to "; Y.Write();
}
else
{
X.Write(); cout << " is NOT equal to "; Y.Write();
}
}
while ( SpaceBarToContinue() );
}
This is the class I'm writing:
class MyFloat
{
enum {MAXDIGIT=20};
char Number[MAXDIGIT+1];
char NumberOfDigits;
public:
friend void AssignValue(MyFloat& X);//remove after the program works
MyFloat();
int Digits();
int MaxDigits();
void Read();
void Write();
MyFloat operator + (MyFloat x);
int operator== (MyFloat x);
};
Here is my == overload function stub:
int MyFloat::operator== (MyFloat x)
{
int Flag=0;
return 1;
}
The only purpose of this is to compare two an array of objects X and Y. They are passed into a == overloaded function. I'm supposed to write the algorithm that compares them. I know how to write the algorithm that compares these two character arrays, thats not the issue, but what I'm failing to understand is how both X and Y get into the the overloaded function to compare them? In the main, the code ( X == Y ) is used to obtain a 0 or 1. How are X and Y passed into the function?
For instance, I would assume my function stub would need to be rewritten with 2 parameters:
int MyFloat::operator== (MyFloat x, MyFloat y)
{
int Flag=0;
return 1;
}
But doing this produces an error back in the main during the function call of ( X == Y ) that states 'Overload "operator==" must be a binary operator (has 3 parameters)'
So I'm totally confused on how to get both Objects of MyFloat into the function to compare them. I'm still fairly new to programming (5-6 months of learning), any plain and simple answers are greatly appreciated.
When you write:
if(a == b)
what it really means is:
if(a.operator==(b))
So in your method:
bool MyFloat::operator==(const MyFloat &x) const
{
// x is b in call above
// (*this) is a in call above
// Your class invariant should guarantee this:
// assert(x.NumberOfDigits < MAX_DIGITS);
// In the scope of your class' methods:
// NumberOfDigits corresponds to this->NumberOfDigits
// Number corresponds to this->Number
if(x.NumberOfDigits != NumberOfDigits) return false;
// Same as: if(x.NumberOfDigits != this->NumberOfDigits) return false;
return strncmp(x.Number, Number, NumberOfDigits) == 0;
// Same as: return strncmp(x.Number, this->Number, this->NumberOfDigits) == 0;
}
Note that I changed the signature of your method. The correct signature returns a bool and takes a const (because you don't want to change the parameter) reference (avoid copying a big object) as parameter. The method is (and must be) const because it's not supposed to modify the object and it must be callable on a const object.
Note that it is possible to define the operator as a non-member function (i.e outside of the class) with the following signature:
bool operator==(const MyFloat &a, const MyFloat &b)
You should use this pointer. For more information: Source
bool MyFloat::operator==(const MyFloat& x) const
{
for(int i = 0; i < x.MaxDigits; ++i)
{
if(x[i] != (*this)[i])
return false;
}
return true;
}
member functions (including overloaded operators) have an implicit this parameter passed in. In your case since you are using a member version of operator== you should only need one parameter the other is this.

Is it possible see the value returned in c++?

So..I'm testing a function with assert: (The value of pBola1 is 1)
assert(BomboTest.TreureBola(1)==pBola1);
BomboTest.TreureBola it's a function that returns a random number (in this case has to return 1) of a list.
cBola* cBombo::TreureBola(int num)
{
int posicio_aleatoria;
posicio_aleatoria= rand() % (num);
return(Boles.TreureElement(posicio_aleatoria));
}
And TreureElement it's a function that returns an element of a dynamic list knowing the position of the element that you want to extract(in this case returns 'retorn' which is 1)
cBola* cLlista::TreureElement(int posicio)
{
int i;
cBola* recorreLlista;
cBola *retorn;
recorreLlista=primer;
retorn = primer;
i=0;
if (posicio == 0)
{
primer = (*primer).getSeguent();
}
else
{
// Busquem la posiciĆ³ //
while(i < posicio)
{
recorreLlista= retorn;
retorn = (*retorn).getSeguent();
i++;
}
(*recorreLlista).setSeguent( (*retorn).getSeguent() );
}
numElements--;
return retorn;
}
And I don't know why but the assert fails. I can see the value returned by TreureElement because I have the pointer 'retorn' but I can't know the value returned by TreureBola..There is some way to see that value returned by TreureBola in the debugger?
PD:I'm using visual studio 2010
Just create a local
cBola* pTemp = BomboTest.TreureBola(1);
assert(pTemp==pBola1);
You could look in the dissasembly and inspect the return registry, but this seems like overkill. The above is the correct approach and others will thank you in the future, when they encounter the same problem.
You can always temporarily change
assert(BomboTest.TreureBola(1)==pBola1);
to`
auto tmp=BomboTest.TreureBola(1);
assert(tmp==pBola1);
and place a breakpoint on the first line.
I would write a small wrapper around assert to use instead:
template <typename T>
void compare(const T& lhs, const T& rhs)
{
if (lhs != rhs)
cout << "The values were not the same! " << lhs << " vs. " << rhs << endl;
assert(lhs == rhs);
}
This will still call assert, but first you'll get some (hopefully) useful output first.
So instead of calling:
assert(BomboTest.TreureBola(1)==pBola1);
You would call:
compare(BomboTest.TreureBola(1), pBola1);
This has an added benefit that you can place a breakpoint here and see see what TreureBola returned in the debugger, too.