I have a const char* const which I need to pass to a method that expects a const char*. How do I do that?.
Also, there is an API that accepts const char **. How do I change in this case?. I tried
const char* const abc="something;
otherAPIThatExpectsConstCharStarStar( &const_cast( abc ) ).
But on linnux this is failing with 'lValue required as '&' operator'.
You don't need to. The last const identifies the type of the variable which holds the string. This means that you cannot modify the variable. But you can freely assign it to some other variable or pass as an argument which doesn't need to be constant anymore.
You really don't need to,as you can see ,when you give an argument to a method,the method will create a copy of the argument,so inside the method, it can only changes the copy,not the original one,unless you pass an address of reference, so,now you have a pointer , it must not be changed ,that's ok ,just pass it to the method, it won't be changed , as I've said.
#include<iostream>
using namespace std;
void fun(const char *p)
{
char tt[10]="dsds";
p=tt;
cout<<"inside_fun"<<endl;
}
int main()
{
int i;
char here[10]="212121";
const char * const pp=here;
fun(pp);
cout<<pp<<endl;
}
This is a bad style code, but it shows the point, just pass it, and change it inside the method,no problem.
#include <iostream>
#include <string>
std::void setString(const char *p) {
std::cout << p << std::endl;
}
int main() {
const char* const cStr ="hello";
setString(cStr);
}
Related
Digging through MSDN, I ran into just another curious line:
// This function returns the constant string "fourth".
const string fourth() { return string("fourth"); }
The full example is buried here: https://msdn.microsoft.com/en-us/library/dd293668.aspx Refined to bare minimum, it looks like this:
#include <iostream>
const int f() { return 0; }
int main() {
std::cout << f() << std::endl;
return 0;
}
A few other tests with different return types demonstrated that both Visual Studio and g++ compile lines like this without a warning, yet const qualifier seems to have no effect on what I can do with the result. Can anyone provide an example of where it matters?
you can not modify the returned object
example:
#include <string>
using namespace std;
const string foo(){return "123";}
string bar(){return "123";}
int main(){
//foo().append("123"); //fail
bar().append("123"); //fine
}
This is almost the same as const variable
#include <string>
using namespace std;
const string foo = "123";
string bar = "123";
int main(){
//foo.append("123"); //fail
bar.append("123"); //fine
}
It is part of the return type. The functions return const string and const int.
In the case of const int, this indeed makes no difference compared to int, because the only thing you can do with an int return value is to copy the value somewhere (in fact, the standard explicitly says that const has no effect here).
In the case of const string, it does make a difference, because a return value of class type can have member functions called on it:
fourth().erase(1);
will fail to compile in the case that fourth() returns a const string, because erase() is not a const method (it tries to modify the string it is called on).
Personally, I never make value-returning functions return a const value, as it unnecessarily constrains the caller (although some people feel that it is useful to prevent writing things like string s = fourth().erase(1);).
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 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;
This should be simple:
I have a static const char* member on my class. I would like to initialize it as a composite string. For example:
const char* s_firstPart = "Hello I'm the first part.";
const char* s_secondPart = "I'm the second part.;
struct MyClass
{
static const char* s_theFinalString;
}
const char* MyClass::s_theFinalString = "Here is the string: " \
+ s_firstPart ++ s_secondPart; // obviously this won't compile
My question is: Is there a way of initializing const char* members as composite char arrays?
The correct answer came from #dauphic in the comments:
No, you can't. You should use std::string instead. Something similar to what you want can be managed with macros, but shouldn't be done.
I have a class which parses the Command line arguments and then returns the parsed value to the client class. For parsing, I need to pass argv to parse function. I would like to pass by reference but from what I know , we never use the '&' symbol when passing arrays. Arrays are not objects that can be passed by reference. Here is my code:
#include <iostream>
#include <fstream>
using namespace std;
class cmdline
{
const char * ifile;
public:
cmdline():ifile(NULL){}
const char * const getFile() const
{
return (ifile);
}
void parse(int argc,const char** argv)
{
//parse and assign value to ifile
// ifile = optarg;
// optarg is value got from long_getopt
}
};
int main(int argc, char ** argv)
{
cmdline CmdLineObj;
CmdLineObj.parse(argc, const_cast<const char**>(argv));
const char * const ifile = CmdLineObj.getFile();
ifstream myfile (ifile);
return 0;
}
1) Is the way argv is treated, correct?
2) Better way to handle, ifile?
3) I want to return ifile as reference, what change should I do, if needed?
My code works the way it is supposed to work, but the reason I came to SO is to "not-just-make-it-work" but do it properly.
Thanks for your help.
EDIT:: After Mehrdad's comment, I edited like this:
class CmdLine
{
const char * ifile;
public:
const char * & getFile() const
{
return (ifile);
}
But I get the error - invalid initialization of reference of type ‘const char*&’ from expression of type ‘const char’
Arrays are not objects that can be passed by reference.
What makes you think that?
1) Is the way argv is treated, correct?
CmdLineObj.parse(argc, const_cast< const char** >(argv));
Why are you const casting that? Instead of casting, you could change your definition of main to const char** argv.
2) Better way to handle, ifile?
Well, there is always std::string, but since all you seem to do is then pass the value to an std::ifstream I don't see a point in using it.
3) I want to return ifile as reference, what change should I do, if needed?
What would be the point of returning a pointer as a reference? Are you expecting callers of getFile to actually change the member that points to such string? You shouldn't be doing that since getFile is a const member function. If you are thinking performance, then returning a reference to a pointer in this case will actually be worse than returning the pointer by value. The string contents are not getting copied when returned from getFile, like they would if ifile was instead an std::string (in which case returning a const reference would make sense).