5

I'm trying to run the following code, taken from "Object Oriented Programming with C++" by Balagurusamy (8th edition):

#include <iostream>
#include <cstring>
using namespace std;

class String
{
char *name;
int length;

public:

String()
{
length = 0;
name = new char[length+1];
}

String(char *s)
{
length = strlen(s);
name = new char[length+1];
strcpy(name,s);
}

void display(void)
{cout<<name<<"\n";}
void join(String &a, String &b);

};

void String :: join(String &a, String &b)
{
length = a.length + b.length;
delete name;
name = new char[length+1];

strcpy(name, a.name);
strcat(name, b.name);
};


int main()
{

char *first = "Joseph ";

String name1(first), name2("Louis"), name3("Lagrange"), s1,s2;

s1.join(name1, name2);
s2.join(s1,name3);

name1.display();
name2.display();
name3.display();

s1.display();
s2.display();

return 0;
}

When I compile with g++, I run into the following log:

g++ -Wall -Werror -Wextra constructors_with_new.cpp -o constructors_with_new.o
constructors_with_new.cpp: In function ‘int main()’:
constructors_with_new.cpp:45:15: error: ISO C++ forbids converting a string constant to ‘char*’ [-Werror=write-strings]
   45 | char *first = "Joseph ";
      |               ^~~~~~~~~
constructors_with_new.cpp:47:28: error: ISO C++ forbids converting a string constant to ‘char*’ [-Werror=write-strings]
   47 | String name1(first), name2("Louis"), name3("Lagrange"), s1,s2;
      |                            ^~~~~~~
constructors_with_new.cpp:47:44: error: ISO C++ forbids converting a string constant to ‘char*’ [-Werror=write-strings]
   47 | String name1(first), name2("Louis"), name3("Lagrange"), s1,s2;
      |                                            ^~~~~~~~~~
cc1plus: all warnings being treated as errors


Then I found the following answer

Why is conversion from string constant to 'char*' valid in C but invalid in C++

and to make it work, I modified the above code

  1. to receive a pointer to const char inside the 2nd constructor (String(char const *s))
  2. inside main(), by changing the initialization of the first name "Joseph", from char * first to char const * first, as suggested by Jeremy Coffin in the answer to the provided link

In this way, it compiles without problems with the following output

Joseph 
Louis 
Lagrange
Joseph Louis 
Joseph Louis Lagrange

What I wonder is whether this is the best way to fix this problem, or if you recommend a different way (maybe another that doesn't need to enter a pointer to a const of type char).

Best,

Stefano

Stefano
  • 88
  • 1
  • 1
  • 6
  • 5
    This is correct (using `const`). That book is outdated. However, in general, if ten C++ developers get asked "what is the best way to do " at least thirteen different answers are guaranteed, so as far as that goes, the "best" alternative is a matter of opinion and wouldn't be appropriate for Stackoverflow. – Sam Varshavchik Apr 24 '22 at 20:01
  • Note that by using `char*` instead of `const char*` you gain no benefits at all, but just have the drawbacks of not being able to pass a `const char*` in: both `strlen` and `strcpy` take `char const*` parameters. – fabian Apr 24 '22 at 20:07
  • Thanks Sam for the reply. I will keep it in mind – Stefano Apr 24 '22 at 20:35
  • How old is that book? Might be worth [getting a better one](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Paul Sanders Apr 24 '22 at 21:55
  • Thanks Paul for the suggestion. It should be from 2019: https://www.amazon.com/Object-Oriented-Programming-C-8th/dp/9389949181/ref=sr_1_5?qid=1650839333&refinements=p_27%3AE+BALAGURUSAMY&s=books&sr=1-5&text=E+BALAGURUSAMY – Stefano Apr 24 '22 at 22:32
  • @Stefano OK, maybe just a typo then. – Paul Sanders Apr 25 '22 at 09:15
  • This should be warning not the error – Supergamer Jan 04 '23 at 13:24

2 Answers2

9

As the comments indicate, you need to use const char*, not char*. It looks like the book is badly out of date.

In C++, a string literal is of type const char[N], where N is the number of characters in the literal plus one for the terminating '\0'.

I was able to make your code compile and run by making the following changed:

  • Change the constructor for String from
    String(char *s)
    to
    String(const char *s)
  • Change the declaration of first from
    char *first = "Joseph ";
    to
    const char *first = "Joseph ";
  • Remove the extraneous semicolon at the end of String::join.

Also, the code would be a lot more legible with proper indentation.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
-1

A string literal in C++ is by default a const char*. That's why you are seeing these warnings where you are trying to assigning a const char* to a char*.

You can simply remove these warnings by casting away the constness of the char*. You can achieve this by using const_cast<char*>

Eg:

char *first = const_cast<char*>("Joseph ");

String name1(first), name2(const_cast<char*>("Louis")), name3(const_cast<char*>("Lagrange")), s1,s2;

This should remove your warning.

Edit: This is not the best advice. My answer is only meant to explain how you can cast away const-ness of the string literal and in no way promotes it. The constness of string literal exists for a reason.

  • 3
    Not the best advice. The warnings are there for a reason. – HolyBlackCat Apr 24 '22 at 20:15
  • I agree. My answer just explains how the person can remove the constness, and in no way promotes the method of removing the const-ness of string literal as it exists for a reason. – Banipreet Singh Raheja Apr 24 '22 at 20:18
  • 1
    A C-string literal in C++ is by default a `char const[N]` (where the N length includes the implicit `'\0'` terminator) that decays into a `char const*` at the earliest opportunity (as is the behavior with all C-style arrays). – Eljay Apr 24 '22 at 20:39
  • Casting away `const` does not remove constness from an object that’s `const`. – Pete Becker Apr 24 '22 at 20:46
  • @PeteBecker Wordings may have been a bit trickier here. I meant we cast away the constness and not remove the constness on the object by using const_cast. – Banipreet Singh Raheja Apr 24 '22 at 20:56