I have a problem in a c++ assignment that cannot be solved. Lets say this - the program works only if the membervariable (a pointer to an char-array) i public. But according to the rules it must be private and one should be able to access it through a public member-method.
Here is the definitions:
private:
char* _strPtr();
int _strLen;
public:
const char* getString();
const char* String::getString() {
return _strPtr;
}
And here in an overloaded member-function the problem arises
const String operator+(const String string, const char *ch) {
String temp;
strcpy(temp.getString, string.getString());
strcat(string.getString(), ch);
return temp;
}
I get error-messages such as
invalid arguments Candidates are ; unsigned int strlen(const char *)
invalid arguments Candidates are ; const char* getString()
I cannot see how this could be solved. I have really tried with everything. Would be glad if someone could come with good tips.
As - I said in th beginning - the program works, but after encapsulating the membervariable and putting a const ahead of the function - it doesn't work any more.
You are defining char* _strPtr();, which is the definition of a function returning a char*. Probably what you meant was to define char* _strPtr;
Related
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 can't find the answer anywhere.
I wrote this class:
class Message {
private:
char senderName[32];
char* namesOfRecipients[];
int numOfContacts;
char subject[129];
char body[10001];
};
And I'm trying to write a constructor with default arguments like this:
Message(char senderName[32]="EVA",
char* Recipents[]={"glados","edi"},
int numOfRec=3,
char subject[129]="None",
char content[10001]="None");
However, it won't accept the recipients default argument no matter how I write it.
Is it even possible to pass a 2D array as a default argument for a constructor?
Sooo many pointers and arrays... if It is C++ why bother? Just write:
class Message {
private:
std::string senderName;
std::vector<std::string> namesOfRecipients;
int numOfContacts;
std::string subject;
std::string body;
};
And:
Message("EVA", {"glados","edi"}, 3, "None", "None");
And everbody is happy...
As Paul mentioned, you should change the declaration of namesOfRecipients to
char **namesOfRecipients;
Then you can have a private const static array of default names in the class and initialize namesOfRecipients with a pointer to its first element. The code is below.
Edit: It's important to understand what the data semantics are here, for example compared to Jarod's solution. The default ctor stores the address of an array of constant pointers to constant character strings. It's not at all possible to copy different characters into a name or to let one of the pointers in the array point to a new name, or to append a name. The only legal thing here is to replace the value of namesOfRecipients with a pointer to a new array of pointers to char.
class Message {
private:
char senderName[32];
char** namesOfRecipients;
int numOfContacts;
char subject[129];
char body[10001];
static const char* defaultNames[];
public:
Message(const char senderName[32]="EVA",
const char** Recipents = defaultNames,
int numOfRec=3,
const char subject[129]="None",
const char content[10001]="None");
};
const char *Message::defaultNames[] = {"Jim", "Joe"};
You can do something like:
namespace
{
char (&defaultSenderName())[32]
{
static char s[32] = "EVA";
return s;
}
const char* (&defaultNamesOfRecipients())[2]
{
static const char* namesOfRecipients[2]={"glados", "edi"};
return namesOfRecipients;
}
}
class Message {
private:
char senderName[32];
const char* namesOfRecipients[2];
public:
Message(char (&senderName)[32] = defaultSenderName(),
const char* (&namesOfRecipients)[2] = defaultNamesOfRecipients())
{
std::copy(std::begin(senderName), std::end(senderName), std::begin(this->senderName));
std::copy(std::begin(namesOfRecipients), std::end(namesOfRecipients), std::begin(this->namesOfRecipients));
}
};
but using std::string/std::vector would be simpler.
Use a separate array of pointers (it's not a 2-D array, though it may look like it) as a default argument:
char* defaultRecipents[] = {"glados","edi"};
class Message {
public:
Message(char senderName[32]="EVA",
char* Recipents[]=defaultRecipents){}
};
Specifying the default array "inline" doesn't work because the compiler "thinks" about it in terms of std::initializer_list, which is only suitable in initialization, not in declaration. Sorry if this sounds vague; I don't have enough experience with this matter.
Note: you might want to use const to declare your strings, to make it clear to the compiler (and your future self) whether the class is or is not going to alter the strings:
const char* const defaultRecipents[] = {"glados","edi"};
class Message {
public:
Message(char senderName[32]="EVA",
const char* const Recipents[]=defaultRecipents){}
};
Here it says const twice to declare that it's not going to:
Change the array elements (e.g. replace one array element, which is a string, by another string or nullptr); and
Change the contents of the strings (e.g. cut a string in the middle, or edit it)
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 learning cpp and In my last assignment I am rewriting the std::string class.
so here is an outline of my code:
string class:
class String {
public:
String(const char* sInput) {
string = const_cast<char*> (sInput);
}
const String operator+(const char* str) {
//snip
print();
}
void print() {
cout<<string;
}
int search(char* str) {
}
private:
char* string;
int len;
};
Oh and I have to say I tried to declare the method as String* operator+(const char* str) and as const String& operator+(const char* str) with no change.
And here is how I run it:
int main(int argc, char* argv[]) {
String* testing = new String("Hello, "); //works
testing->print();//works
/*String* a = */testing+"World!";//Error here.
return 0;
}
The full error goes like such:
foobar.cc:13: error: invalid operands
of types ‘String*’ and ‘const char
[7]’ to binary ‘operator+’
I looked up on Google and in the book I am learning from with no success.
any one with suggestions? (I am pretty sure I am doing something foolish you will have to forgive me I am originally a PHP programmer) can any one point me to what am I missing?
You probably don't want to use a pointer to your String class. Try this code:
int main(int argc, char* argv[]) {
String testing = String("Hello, "); //works
testing.print();//works
String a = testing+"World!";
return 0;
}
When defining new operators for C++ types, you generally will work with the actual type directly, and not a pointer to your type. C++ objects allocated like the above (as String testing) are allocated on the stack (lives until the end of the "scope" or function) instead of the heap (lives until the end of your program).
If you really want to use pointers to your type, you would modify the last line like this:
String *a = new String(*testing + "World!");
However, following the example of std::string this is not how you would normally want to use such a string class.
Your operator+ is defined for String and const* char, not for String*. You should dereference testing before adding it, i.e.:
String a = (*testing) + "World";
Though in this case I don't see the point in making testing a pointer in the fist place.
Edit: Creating a string without pointers would look like this:
String testing = "Hello, ";
or
String testing("Hello, ");
(both are equivalent).