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)
Related
When I initialize the constructor with the given data type of the parameter, I find that it goes wrong with the explaination that " const char* values cannot be assigned to char* entities".
class TString
{
private:
char* m_pData;
int m_nLength;
public:
TString();
TString(const char* pStr);
······
}
TString::TString(const char* pStr) {
this->m_pData = pStr;
}
What should I do to solve this problem? If possible, give me a right example.
Thanks in advance and apolpgize for my ignorance.
Const char * generally are prefined static compiled strings that cannot be changed because they are locked in the source code, or they come from some immutable source. This is in part, why they are marked const to prevent people from trying to change them.
The easiest solution to this problem is to take the const char * and make a copy of it on the heap, then it is no longer constant.
For example:
#include <string.h> // for strdup
...
TString::TString(const char* pStr) {
m_pData = strdup(pStr); // this will malloc and copy the string accepting const char * as input.
}
One thing you will need to consider, the m_pData is now on the heap, so in the destructor, you will want to free this data otherwise you will have a memory leak.
TString::~TString(){
free(m_pData);
}
You will also want in the TString() constructor to set the m_pData=NULL too.
This will work with strings, but if it's binary data i.e. no terminator allocate the data using malloc and use a memcpy, like:
m_pData=(char *)malloc(m_nlength*sizeof(char));
memcpy(m_pData,pStr,m_nlength);
Or some such.
I have class Citizen { string name,address ... } and then I have class TaxRegister.
class TaxRegister
{
public:
bool Add_citizen ( const string& name, const string& addr );
private:
static const int m_Size=1000;
int m_Index,m_IncrementedSize;
Citizen * m_People[m_Size];
};
bool TaxRegister::Add_citizen( const string& name, const string& addr )
{
....
m_People[m_Index++] = new Citizen( name,addr );
}
The problem is, when I have to add more then 1000 people into my array;
I tried to do this:
Citizen *tmp[m_IncrementedSize*=2];
for (int i=0; i < m_Index; i++ )
tmp[i]=m_People[i];
delete [] m_People;
m_People=tmp;
m_IncrementedSize*=2;
But the compilator gives me this:
incompatible types in assignment of ‘CCitizen* [(((sizetype)) + 1)]’ to ‘CCitizen* [1000]’
Does anybody know how to fix it ? Thank you.
Use std::vector<Citizen> instead of an array and the problem will likely disappear by itself. A standard container like std::vector manages all memory automatically for you. You will end up with no new and delete[] at all in your code.
Just to give you an idea, this is what your Add_citizen function would then look like:
void TaxRegister::Add_citizen( const string& name, const string& addr )
{
m_People.push_back(Citizen(name, addr));
}
You are already using std::string instead of char const *. That's good. Using std::vector instead of arrays is exactly the same improvement.
If you want to stick to arrays, just make sure that the size parameter in the array declaration is actually a constant, rather than a variable. And then allocate a new array.
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.
What is the problem in my code? It does not compile..
class FileNames
{
public:
static char* dir;
static char name[100];
static void Init3D()
{
FileNames::dir = "C://3D//";
FileNames::name = "abc";
}
};
You cannot assign to an array, so FileNames::name = "abc" fails (char arr[4] = "abc" works, however, because this is a direct initialization, not assignment). Either use a char* here as well, or use strcpy to copy data to the array or better a std::string which avoids many of the downsides of raw strings.
Most importantly you need to define your static members somewhere at global scope, outside a function:
char FileNames::name[100];. At this time initialization syntax using = would be possible even with the array, but the string to be assigned needs to have the same length as the array.
There are two problems with your code:
1) You've duplicated the variable name (with two different types).
2) You can't initialise static members like that (see example below).
The last thing isn't a problem as such, but you should consider using std::string instead, as that encapsulates string functionality so that you don't need to deal with raw pointers. It's a lot less painful, especially if you're new to this sort of thing.
Change it to this:
// Header file
class FileNames
{
private:
static char* name;
public:
static char* dir;
};
CPP file
#include "FileNames.h"
char* FileNames::name = "abc";
char* FileNames::dir = "C://3D//";
// Now use your class...
Try initializing like this:
class FileNames
{
public:
static char* dir;
static char name[];
};
char *FileNames::dir = "C://3D//";
char FileNames::name[100] = "abc";
Did you remember to actually define the static members outside of the class? Also, I don't believe you need to resolve the scope unless you're actually outside of the class.
Use:
FileNames::dir = new char[strlen("C://3D//")];
strcpy(FileNames::dir, "C://3D//");
strcpy(FileNames::name, "abc");
Also, don't forget to #include <cstring> and to later delete[](FileNames::dir)
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).