I'm getting 8 errors in this program. Can anyone help?
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
class Name {
const char* m_value;
void allocateAndCopy(const char* value) {
delete[] m_value;
m_value = new char[strlen(value) 1];
strcpy(m_value, value);
}
public:
Name() :m_value(nullptr) {
};
Name(const char* value) :m_value(nullptr) {
allocateAndCopy(value);
}
Name(Name& N) {
*this = N;
}
Name operator=(const Name& N) {
allocateAndCopy(N.m_value);
return this;
}
~Name() {
delete[] m_value;
}
void display(ostream& os)const {
os << m_value;
}
void read(istream& is) {
char val[1000];
getline(is, val);
allocateAndCopy(val.c_str());
}
};
ostream& operator<<(ostream& os, Name& N) {
N.display(os);
return os;
}
istream& operator<<(istream& is, Name& N) {
return N.read(is);
}
The errors I'm getting are:
Severity Code Description Project File Line Suppression State
Error (active) E0167 argument of type "const char *" is incompatible with parameter of type "char *"
and more.
CodePudding user response:
There are at least four fundamental bugs/problems with the shown code.
strcpy(m_value, value);
m_value is a const char *, a pointer to constant characters. "constant" means that you can't strcpy() over them, of course.
Instead of immediately assigning the result of new [] to m_value, and then strcpy() into it, the result of new [] should be stored in a temporary char *, then strcpy()ed; and then the temporary char * can finally be placed into the m_value.
Name(Name& N) {
A proper copy constructor should take a const reference as a parameter, this should be Name(const Name &N).
Name(Name& N) {
*this = N;
}
This constructor fails to initialize the m_value class member. The constructor then calls the overloaded operator=. It will, eventually, attempt to delete m_value, which was never initialized. This results in undefined behavior, and a likely crash. You will need to fix this bug as well.
Name operator=(const Name& N) {
An overloaded operator= is expected to return a reference to this, not a brand new object. This should return a Name &, and actually return *this.
CodePudding user response:
There are many problems with your code:
m_valueis aconst char*, ie a pointer to read-only memory, but you are trying to modify the data it is pointing at (viastrcpy()), so it needs to be achar*instead, ie a pointer to writable memory.allocateAndCopy()doesn't account forvaluebeingnullptr. Callingstrlen()andstrcpy()with anullptras input is undefined behavior.the copy constructor is not initializing
m_valuebefore callingoperator=, thus makingallocateAndCopy()calldelete[]on an invalid pointer, which is also undefined behavior.operator=is declared to return a newNameobject by value, butthisis aName*pointer. You need to return*thisbyName&reference instead. You are also not accounting for the possibility of self-assignment (ie, assigning aNameobject to itself).read()is callingstd::getline()which requires astd::stringnot achar[]. And achar[]does not have ac_str()method. And you are not checking ifgetline()is even successful before passingvaltoallocateAndCopy().operator<<should take in aNameobject byconstreference.your stream extraction operator is named
operator<<(the name of the stream insertion operator). It needs to be namedoperator>>instead. Also, it needs to returnisby reference, to allow the caller to chain multiple>>reads together. It is trying to return the return value ofread(), which isvoid.
With that said, try something more like this instead:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
//#include <string>
#include <cstring>
class Name {
char* m_value = nullptr;
void allocateAndCopy(const char* value) {
delete[] m_value;
m_value = nullptr;
if (value) {
m_value = new char[std::strlen(value) 1];
std::strcpy(m_value, value);
}
}
public:
Name() = default;
Name(const char* value) {
allocateAndCopy(value);
}
Name(const Name& N) {
allocateAndCopy(N.m_value);
}
Name& operator=(const Name& N) {
if (&N != this) {
allocateAndCopy(N.m_value);
}
return *this;
}
~Name() {
delete[] m_value;
}
void display(std::ostream& os) const {
os << m_value;
}
void read(std::istream& is) {
char val[1000] = {};
if (is.getline(val, 1000))
allocateAndCopy(val);
/* alternatively:
std::string val;
if (std::getline(is, val))
allocateAndCopy(val.c_str());
*/
}
};
std::ostream& operator<<(std::ostream& os, const Name& N) {
N.display(os);
return os;
}
std::istream& operator>>(std::istream& is, Name& N) {
N.read(is);
return is;
}
