I have this class:
#ifndef String_H
#define String_H
class String
{
public:
String();
String(const char*, ...);
String(const String&);
~String();
const String& operator= (const char*);
const int capacity();
void clear(){ string[0] = '\0'; }
const char* getString()const { return string; }
const int lenght()const { return length; }
private:
int length;
char *string;
void alloc(const int);
};
#endif
And in the implementation i have this:
#include <wtypes.h>
#include "String.h"
#include "Log.h"
#include <stdio.h>
String::String()
{
alloc(1);
clear();
}
String::String(const char* _string, ...)
{
//length = 0;
if (_string != NULL)
{
static char buff1[4096];
va_list args;
va_start(args, _string);
int res = vsprintf_s(buff1, 4096, _string, args);
va_end(args);
if (res > 0)
{
alloc(res + 1);
strcpy_s(string, length, buff1);
}
}
else
{
alloc(1);
clear();
}
}
String::String(const String& _string)
{
if (&_string != NULL)
{
alloc(_string.lenght());
strcpy_s(string, length, _string.getString());
}
else
{
alloc(1);
clear();
}
}
String::~String()
{
delete[]string;
}
const String& String::operator= (const char* str)
{
if (strlen(str) > sizeof(string) + 1)
{
delete[] str;
alloc(strlen(str) + 1);
strcpy_s(string, length, str);
}
else
{
strcpy_s(string, length, str);
}
return (*this);
}
void String::alloc(const int size)
{
length = size;
string = new char[size];
}
And when in main I do:
String a;
String b("hi");
a = b;
The compiler says me that:
Error 2 error LNK2019: unresolved external symbol "public: class String const & __thiscall String::operator=(class String const &)" (??4String##QAEABV0#ABV0##Z) referenced in function _main C:..\main.obj
AND
Error 3 error LNK1120: 1 unresolved externals C:..\MyLibrary.exe
This is making me crazy. Please help me.
I can't see what i'm doing wrong.
This line invokes the assignment operator:
a = b;
You are missing an assignment operator that takes a String.
This is not the assignment operator that will be called:
const String& String::operator= (const char* str)
A typical assignment operator would have the following signature:
String& String::operator= (const String& s)
Please read up on the "Rule of 3". What is The Rule of Three?
Related
I am doing a custom string class in C++. However, when I debugged my code, the system said that:
Error E0415:no suitable constructor exists to convert from "const char" to "string"
Here is my header file where my custom string class is defined:
#ifndef _STRING
#define _STRING
#include <iostream>
class string {
private:
char* s = nullptr;
unsigned int size = 0;
public:
string();
~string() { delete s; };
void operator=(const char*);
friend std::ostream& operator<<(std::ostream&, string&);
};
#endif
string::string()
: s{ nullptr }
{
s = new char[1];
s[0] = '\0';
}
void string::operator=(const char* source)
{
if (source == nullptr) {
s = new char[1];
s[0] = '\0';
}
else {
size = strlen(source) + 1;
s = new char[size];
for (int k = 1; k < (strlen(source) + 1); k++) {
s[k] = source[k];
}
}
}
std::ostream& operator<<(std::ostream& output, string& result)
{
output << result.s;
return output;
}
And here is my main file which I tried to comply:
#include "custom_string.h"
int main()
{
string a;
a = "testfile";
std::cout << a;
system("pause");
return 1;
}
As you can see, I have declared a constructor to convert const char to my custom string by overloading assignment operator. However, there should be something wrong in my code and I could not find out it. Please help me and thank you
Thanks everyone, I have done to fix it. As it turned out, I have to declare one more constructor to covert between my custom string and const char. That is something like this:
string::string(const string& t){}
string& string::operator=(const char&source){}
I need to overload an assignment operator += and concatenate two MyString(class) objects in C++.I'm using CodeBlocks.I need to allocte memory dynamically so I've to use new keyword to overload += operator.The following is the code is used.
MyString.h
#ifndef MYSTRING_H
#define MYSTRING_H
class MyString
{
private:
const char* str;
int length;
public:
MyString();
~MyString();
MyString(const char*);
MyString(const MyString&);
void operator = (const MyString&);
int getLength() const;
MyString operator + (const MyString&);
MyString operator += (const MyString&);
void display();
};
#endif // MYSTRING_H
MyString.cpp
#include "MyString.h"
#include <cstring>
#include <iostream>
MyString::MyString()
{
str="\0";
length=0;
}
MyString::MyString(const char* Str)
{
str=Str;
int str_length=0;
while (str[str_length] != '\0') {
str_length++;
}
length=str_length;
}
MyString::MyString(const MyString &temp)
{
str=temp.str;
length=temp.length;
}
void MyString::operator = (const MyString &deepcopy)
{
str=deepcopy.str;
length=deepcopy.length;
}
MyString MyString::operator += (const MyString& strrr) // here I need to overload assignment operator with new keyword dynamically.
{
str = str+strrr.str; // this is not a correct code.
}
int MyString::getLength() const
{
return length;
}
void MyString::display()
{
std::cout << str<<std::endl;
std::cout << "string length: " <<length<<std::endl;
}
MyString::~MyString()
{
}
main.cpp
#include <iostream>
#include <MyString.h>
int main()
{
char str[20];
MyString S1;
std::cout << "Enter a string : " <<std::endl;
std::cin >> str;
MyString S2(str);
S2.display();
MyString S3=S2;
S3.display();
MyString S4=S3;
S4.display();
MyString S5; // This S5 object that I'm trying to use to overload += operator
S5 = S3 + S4;
S5.display();
return 0;
}
enter code here
I have searched these kind of questions, but I don't still understand why my code has error and how to implement it...
What I want to do is create a class, which can be assigned by string and char* just like std::string...http://www.cplusplus.com/reference/string/string/operator=/
string (1) string& operator= (const string& str);
c-string (2) string& operator= (const char* s);
I can write
string str1 = "haha"; //way(2)
string str2 = str1; //way(1)
So, I write this class...
class LinkedList
{
private:
ListNode *first;
public:
LinkedList():first(nullptr) {};
LinkedList(const string &str);
LinkedList& operator=(const string &str);
LinkedList& operator=(const char *s);
void Print_LinkedList();
void Push_back(char c);
// void Insert();
// void Delete();
// void Invert();
// void Clear();
};
And, the method part is...
LinkedList& LinkedList::operator=(const string &str)
{
if (str.length()%3 != 1)//legal string_input.length is 3n+1
{
cout << "LinkedList building error" << endl;
}
else
{
for (unsigned int i = 0; i < str.length(); i+=3)
{
this->Push_back(str.at(i));
}
}
return *this;
}
LinkedList& LinkedList::operator=(const char *s)
{
// if (???) //please give me some suggestions...
// {
// cout << "LinkedList building error" << endl;
// }
// else
// {
// for (???) //please give me some suggestions...
// {
// this->Push_back(???); //please give me some suggestions...
// }
// }
this->Push_back('x');
return *this;
}
And, the main part is...
int main()
{
LinkedList linkedlist1;
linkedlist1.Push_back('x');
linkedlist1.Push_back('a');
linkedlist1.Print_LinkedList();
string str_test = "H->a";
LinkedList linkedlist2(str_test);
linkedlist2.Print_LinkedList();
string str_test2 = "H->A->h->o";
LinkedList linkedlist3 = str_test2;
linkedlist3.Print_LinkedList();
LinkedList linkedlist4 = "x"; //there's an error in this line
linkedlist4.Print_LinkedList();
return 0;
}
Then, the compiler says,
"error: conversion from 'const char [2]' to non-scalar type 'LinkedList' requested|"
Could you tell me...
1.why dose my code have the compiler error?
2.how can I fix the bug?
3.some suggestions for implementing in the "LinkedList& LinkedList::operator=(const char *s){//how should I write here}"
Thanks for your help.
I was just experimenting and making my own string class. (Mainly because there is some stuff I wanted to build in custom methods like "toBase64" etc. Anyways, I was wondering how you could access the private member of char* when you use &String[0].
I thought you could use operator-overloading but I currently only have it as String[0] returns the char*. (I know & is the pointer operator).
String.h
namespace CoffeeBeans
{
class _declspec(dllexport) Coffee_String
{
char* String;
int StringLength;
public:
Coffee_String();
Coffee_String(LPCSTR CString);
LPSTR operator[](int);
~Coffee_String();
};
}
String.cpp
#include "stdafx.h"
#include "String.h"
#include <Windows.h>
CoffeeBeans::Coffee_String::Coffee_String() {
this->String = nullptr;
this->StringLength = 0;
}
CoffeeBeans::Coffee_String::~Coffee_String() {
if (String != nullptr) {
delete[] this->String;
this->String = nullptr;
this->StringLength = 0;
}
}
CoffeeBeans::Coffee_String::Coffee_String(LPCSTR CString) {
int StringLength = strlen(CString) + 1;
this->String = new char[StringLength]();
this->StringLength = StringLength - 1;
memcpy_s(this->String, StringLength, CString, StringLength);
}
LPSTR CoffeeBeans::Coffee_String::operator[](int)
{
return this->String;
}
Main.cpp
case WM_CREATE:{
CoffeeBeans::Coffee_String String("Test");
//I want to be able to do
//strcpy_s(&String[0], 3, "hi"); //Copy "hi" into the private variable char*String.
//I know this isn't a practical use, I wanted quick example (I would really pass it to recv (WinSock2))
MessageBeep(0);
break;
}
Your operator[] is returning the wrong value. In order for &String[index] to access the correct memory address, operator[] needs to return a reference to the character at the specified index, not return the string pointer itself, as you are currently doing.
If you look at the actual declaration of std::string::operator[], you will see that it returns a std::string::reference (aka char &) or std::string::const_reference (aka const char &) (depending on whether it is being called on a non-const or const std::string object).
Try something more like this:
String.h
namespace CoffeeBeans
{
class _declspec(dllexport) Coffee_String
{
char* String;
int StringLength;
public:
Coffee_String();
Coffee_String(const Coffee_String &src);
Coffee_String(const char *src);
~Coffee_String();
char& operator[](int index);
const char& operator[](int index) const;
Coffee_String& operator=(const Coffee_String &rhs);
};
};
String.cpp
#include "stdafx.h"
#include "String.h"
#include <algorithm>
#include <cstring>
CoffeeBeans::Coffee_String::Coffee_String() {
String = nullptr;
StringLength = 0;
}
CoffeeBeans::Coffee_String::Coffee_String(const CoffeeBeans::Coffee_String &src) {
StringLength = src.StringLength;
String = new char[StringLength+1];
std::copy(src.String, src.String+StringLength, String);
String[StringLength] = 0;
}
CoffeeBeans::Coffee_String::Coffee_String(const char *src) {
StringLength = std::strlen(str);
String = new char[StringLength+1];
std::copy(src, src+StringLength, String);
String[StringLength] = 0;
}
CoffeeBeans::Coffee_String::~Coffee_String() {
delete[] String;
String = nullptr;
StringLength = 0;
}
char& CoffeeBeans::Coffee_String::operator[](int index)
{
return String[index];
}
const char& CoffeeBeans::Coffee_String::operator[](int index) const
{
return String[index];
}
CoffeeBeans::Coffee_String& CoffeeBeans::Coffee_String::operator=(const CoffeeBeans::Coffee_String &rhs);
{
Coffee_String temp(rhs);
std::swap(String, temp.String);
std::swap(StringLength, temp.String);
return *this;
}
Main.cpp
case WM_CREATE: {
CoffeeBeans::Coffee_String String("Test");
strcpy_s(&String[0], 3, "hi"); //Copy "hi" into the private variable char *String...
// note that the content of String will become "hi\0t\0", not "hi\0"
// and StringLength will still be 4...
MessageBeep(0);
break;
}
I have been trying to implement Stack that holds objects of MyString class (it is exercise from one of the books). I managed to push those objects to container, but when I want to call function void print() I get an error:
error: passing 'const MyString' as 'this' argument of 'void MyString::print()' discards qualifiers [-fpermissive]
cp->print();
Here is the code:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
class MyString
{
string a;
public:
MyString(string aa) : a(aa)
{
}
void print()
{
cout << a << endl;
}
};
class StringStack {
static const int size = 100;
const MyString* stack[size];
int index;
public:
StringStack();
void push(const MyString* s); // does this have to be const?
const MyString* pop(); // does this have to be const?
};
StringStack::StringStack() : index(0) {
memset(stack, 0, size * sizeof(MyString*));
}
void StringStack::push(const MyString* s) {
if(index < size)
stack[index++] = s;
}
const MyString* StringStack::pop() {
if(index > 0) {
const MyString* rv = stack[--index];
stack[index] = 0;
return rv;
}
return 0;
}
MyString s0("pralines & cream");
MyString s1("fudge ripple");
MyString s2("jamocha almond fudge");
MyString s3("wild mountain blackberry");
MyString s4("raspberry sorbet");
MyString s5("lemon swirl");
MyString s6("rocky road");
MyString s7("deep chocolate fudge");
MyString iceCream[] = {s0,s1,s2,s3,s4,s5,s6,s7};
const int iCsz =
sizeof iceCream / sizeof *iceCream;
int main() {
StringStack ss;
for(int i = 0; i < iCsz; i++)
ss.push(&iceCream[i]);
const MyString* cp;
while((cp = ss.pop()) != 0)
{
cout << (long)cp << endl;
// cp->print(); // won't work
}
} ///:~
You can either:
make void MyString::print() const, which seems to be reasonable.
or :
make const MyString* pop(); to return non const pointers.
I dont think that StringStack should store pointers to const objects. If you plan to never modify MyString objects from your stack, then keep them internally as const. The choice depends on your requirements.