I'm kinda of new at c++, so I need some help. I have to make a function tha books ticket for an event.
void Event::book(int row, int seat, Date date, char *name, char *note)
{
if(this->date==date && strcmp(this->name,name)==0)
{
if(hall.seatsInHall[row-1][seat-1].isFree()==true)
{
hall.seatsInHall[row-1][seat-1].isFree()=false; // here it gives me non-lvalue in assignment
hall.seatsInHall[row-1][seat-1].getNote()=note; // here it gives me non-lvalue in assignment
hall.seatsInHall[row-1][seat-1].getNote()=note; // here it gives me non-lvalue in assignment
cout<<"Seat Booked.";
}
else cout<<"This seat is already taken or bought.";
}
else cout<<"Error.";
}
What can I do to not show this mistake?
The problem arises because the stuff on the left side of the assignment statements are not lvalues i.e. you cannot assign values to them. The most likely cause is that getNote() and isFree() are returning-by-value. A function can return an lvalue if (and only if) it returns a reference.
You need to make sure that isFree() and getNote() return non-const references.
For the two functions having problems in your post, they could look like:
bool& isFree()
char*& getNote()
While this should fix your errors, in the case of getNote, it's not very pretty. Furthermore, it's not clear which object has ownership of the char* data and that could lead to memory leaks later. A nicer solution would be to change note to std::string instead of char*.
Your original function signature would then look like:
void Event::book(int row, int seat, Date date, char *name, std::string note)
And the signature of getNote() would be:
std::string& getNote()
Related
So my task is to create a function with signature: list<Person>::iterator SearchPos(list<Person> &Mylist, Person &person). Which would later get the appropraite position for the person, in order of birth, to be inserted into the list. Its return type should be an Iterator.
I have tried doing the following :
list<Person>::iterator SearchPos(list<Person> &MyList, Person &person)
{
}
int main()
{
char Dot;
string Dummy;
string Name;
int Day, Month, Year;
fstream MyFile;
MyFile.open("Kontakte.txt");
list<Person> BirthdayList; // Creating list of type Person
if(MyFile.is_open()) {cout << "File opened successfully." << endl;};
getline(MyFile, Name, ','); //Get line until "," is reached
MyFile >> Day >> Dot;
MyFile >> Month >> Dot;
MyFile >> Year;
getline(MyFile, Dummy); //Gets rid of \n char.
Person P1 (Name, Day, Month, Year);
SearchPos(&BirthdayList, &P1);
but even without the body of SearchPos() function I get the error :
invalid initialization of non-const reference of type 'std::__cxx11::list<Person>&' from an rvalue of type 'std::__cxx11::list<Person>*'|
Edit
Thanks a lot for the help with that error message it would take me embarrasingly long to figure that one out. The answer to my orginal question is as follows
list<Person>::iterator SearchPos(list<Person> &MyList, Person &person)
{
list<Person>::iterator pos;
//body of the function
return pos;
}
This will make the function return an iterator as wanted by my task.
After some getting used to, the compiler error is actually clear. Maybe this will help you to decipher it.
invalid initialization of non-const reference of type 'std::__cxx11::list&' from an rvalue of type 'std::__cxx11::list*'|
std::__cxx11::list<Person> is actually list<Person> in your code. The standard library just adds some namespaces. Maybe if we switch the example to int, it is clearer.
int SearchPos(int& index){} // let's define a function taking a reference to `int`.
int main() {
int my_index;
SearchPos(&my_index);
}
would similarly result in
invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int*'|
So the problem is that you cannot convert int* to int&.
Why? Well, they are different types, and you cannot convert between them.
Where is int* coming from? You are getting the type int*, since the operator & returns an address to the int, thus a pointer to int (int*). (extra, the returned address is a rvalue, since it itself does not have an address.)
So either you make sure that the type you are inputting corresponds to the signature of the method:
int SearchPos(int* index){}
int main() {
int my_index;
SearchPos(&my_index);
}
, or, what you should do, since the signature is set, you make sure you pass a reference:
int SearchPos(int& index){}
int main() {
int my_index;
SearchPos(my_index);
}
You need to call the function like this:
SearchPos(BirthdayList, P1);
As mentioned in the comments you were passing the parameters as pointers when your function was looking for a reference. Using the ampersand (&) returns a pointer to your object. I know it may be confusing and seem like you need to pass in the address since your function accepts a reference but you don't need to do that. Declaring it as a reference in the function parameters is all you need to do.
I'm new to C++ programming and in my OPP class we were requested to create a phone book.
Now, in the lecture the Professor said something about that if you want to make sure that your variable that is being injected to a method doesn't get changed you must put const on it.
here is my code so far.
private:
static int phoneCount;
char* name;
char* family;
int phone;
Phone* nextPhone;
public:
int compare(const Phone&other) const;
const char* getFamily();
const char* getName();
and in Phone.cpp
int Phone::compare(const Phone & other) const
{
int result = 0;
result = strcmp(this->family, other.getFamily());
if (result == 0) {
result = strcmp(this->name, other.getName);
}
return 0;
}
I keep getting "the object has type qualifiers that are not compatible with the member"
when I try to call to strcmp inside my compare function.
I know that I can just remove the const in the function declaration and it will go away, but I still doesn't understand why it's showing in the first place.
Help would be greatly appreciated.
You need to add const qualifier for getters const char* getFamily() const;. This way these getters can be invoked on objects of type const Phone & that you pass into function.
Also other.getName should be other.getName().
Your signature
int Phone::compare(const Phone & other) const
means inside that function you need to ensure you don't change the Phone instance.
At the moment, your function calls const char* getFamily() (and getName, which you've missed the () call from). Neither of these functions are const, hence the error.
If you mark these as const too, it will be ok.
In addition to the other answers that correctly suggest const qualifying your getters, you can access the data members of other directly, avoiding those calls.
int Phone::compare(const Phone & other) const
{
int result = strcmp(family, other.family);
if (result == 0) {
result = strcmp(name, other.name);
}
return result;
}
I am working on a homework for class on overloading operators. The problem I am having is with a char.
RetailItem &RetailItem::operator=(const RetailItem &objRetail) {
this->description = objRetail.getDescription();
this->unitsOnHand = objRetail.getUnitsOnHand();
this->price = objRetail.getPrice();
return *this;
}
I am getting a message on Visual Studio:
a value of type const char * cannot be assigned to an entity of type char *.
I have done some research and not found anything. If anyone can help, thanks in advance.
EDIT:
I will add the getDescription function to provide more information. Also the description is a *char.
const char *RetailItem::getDescription() const{
return description;
}
Probably RetailItem::description is char* and RetailItem::getDescription casts this char* to const char* and returns that. You can add const qualifiers implicitly, but you cannot remove them the same way in the assignment:
this->description = objRetail.getDescription();
And you probably shouldn't. This will make two RetailItems referring to the same resource without managing its lifetime properly, as well as not freeing the memory held previously (if it is indeed a pointer to a dynamically allocated array).
This boils down to: you should prefer using std::string over arrays.
Reason might be mismatch between data type of "member variables" which you used in the class and the return values of the function.
const char *RetailItem::getDescription() const{
return description;
}
Remove const before function , keep it char *RetailItem::getDescription() const only .It should work
I'm here looking at some C++ code and am not understanding something. It is irrelevant but it comes from a YARP (robot middleware) tutorial which goes with the documentation.
virtual void getHeader(const Bytes& header)
{
const char *target = "HUMANITY";
for (int i=0; i<8 && i<header.length(); i++)
{
header.get()[i] = target[i];
}
}
Now, header is a reference to const and thus cannot be modified within this function. get is called on it, its prototype is char *get() const;. How can header.get() be subscripted and modified ? The program compiles fine. I may have not understood what happens here but I'm basing myself on what I've read in C++ Primer...
I would very much appreciate a little clarification!
Have a nice day,
char *get() const;
The right hand const means "this member doesn't alter anything in the class that's not mutable", and it's honoring that - it isn't changing anything. The implementation is probably something like this:
char *Bytes::get() const
{
return const_cast<char *>(m_bytes);
}
The pointer that is being returned, however, is a simple "char*". Think of it this way:
(header.get())[i] = target[i];
// or
char* p = header.get();
p[i] = target[i];
Whoever designed the interface decided that the content of a const Byte object can be modified by stuffing values into it. Presumably they've done whatever hacks they needed to make header.get()[i] modifiable. I wouldn't use this code as an exemplar of good interface design.
Looking at the doc:
struct Bytes {
char* get() const; // works
char*& get() const; // would not work
char* mem_;
};
This code is perfectly valid, even though it is bad practice. The
problem is that a copy of the pointer is made and the constness of the
class is lost. constness in C++ is largely conceptual and easy to
break (often even without consequences). I'd complain to the
implementer. It should look like this:
struct Bytes {
char* get(); // works
const char* get() const; // would not work
char* mem_;
};
header.get() should returns char*, assuming it as base address and indexed with [i] and string in target coped to that location.
#antitrust given good point, return address can't be modified by address content can e.g.
char x[100];
char* get() const
{
return x;
}
int calling function you can do like:
get()[i] = target[i];
it will copy target string to x, this method can be useful when x is private member to class, and you are to copy in x.
Edit if get() is a inline function then calling get() function in a loop will not effect performance., I mean such function should be defined inline.
I'm new to this so I know this is probably something simple.
I have a function like this
void GroceryList::addRecord(char* itemName, char* itemType, char rating){
//do some code;
}
My problem is I am having trouble creating proper arguments to pass to the function.
I've tried something like
void main() {
string itemName;
cin >> itemName;
string itemType;
cin >> itemType;
string rating;
cin >> rating;
gradeBook.addRecord(itemName, itemType, rating);
}
I didn't expect it to work as the function is expecting char* but I can't for the life of me figure out how to get the user input into a variable that I can pass to the function. I've been search for literally 13 hours trying what I can find but no luck so far.
Well, don't use char*.
void GroceryList::addRecord(const std::string& itemName, const std::string& itemType, const std::string& rating) { /* ... */ }
You can get const char* (not char*) from string with c_str() member function, e.g. itemName.c_str(), but unless you're doing interop with C libraries, you don't need that.
Change the function prototype to
void GroceryList::addRecord(string itemName, string itemType, string rating){
//do some code;
}
I also recommend const correctness in your code, if you are not going to change the arguments, pass them by ref with const (for performance)
void GroceryList::addRecord(const string& itemName, const string& itemType, const string& rating){
//do some code;
}
All depends on the actual method body which you didn't describe.
Use std::string::c_str(); that's what it's for:
gradeBook.addRecord(itemName.c_str(), itemType.c_str(), rating.c_str());
This function returns a const char *. However, the addRecord function doesn't seem to be const-correct, so you need to fix that.
You can use string and then when passing just call c_str() on the string. For the rating you can just use a char.
Then calling the function looks like:
gl.addRecord(itemName.c_str(), itemType.c_str(), rating);
For this to work you'll need to change the function signature to const char* instead of char*.
The simple answer is that you can't. If you can modify
GroceryList::addRecord, change it to use std::string const&. If you
can't modify it, then you have to ask the question: why does it use
char*? There are two possible answers: the author didn't understand
const, or was too lazy to use it, and in fact doesn't modify the
pointed to strings. In this case, something like
const_cast<char*>( itemName.c_str() ) can be used; it's wordy, but
that's the price you pay when the code's author doesn't do his job
correctly. The other possible answer is that the code does modify
something through the pointer. In this case, the only solution involves
making a copy of the string into a char[], and passing it.