Even though the statement
string hello = "hi"
looks like its an assignment, this is actually an object construction. The compiler is looking for a suitable constructor to create the object with, but only the default constructor is available, so compilation fails.
You have at least two options: either construct the object, then assign to it e.g.
int main()
{
string hello; hello = "hi"; }
or add a constructor to your string class that takes a
const char *
as an argument. In order to do that, we do have to jump through a couple of hoops to allow for the fact the "hi" is of type
const char*
class string {
char *data;
string() { } string(char *str) : data(str) { } string(const char *str) { data = const_cast<char *>(str);
}
string& operator=(const char* str) {
if(data != str)
data = str;
return *this;
}
};
int main()
{
string hi = "hello"; }
As noted earlier, we need to cast away constness for the constructor, which is a sign that we probably do not have good design for our data members. Casting away constness signals to the compiler that you "Know What You Are Doing", and the compiler can accept the code without complaint. Note that the object that
string::data
points to may still be a constant item, so if at some point you try to do something like this:
class string {
void captialize_first() {
if(data)
*data = toupper(*data);
}
};
main()
{
string hi = "hello";
hi.capitilze_first();
}
you will almost certainly get a program crash.*
*
There may be some architectures and/or compiler combinations out there which do not implement string constants as constant objects, but as far as I know x86, x86-64, arm32 and arm64 all do.