I'm just toying around to watch how defining operators work. The following code gives me an error about "No candidate functions found".
Any criticism other than that of the root cause is welcome, too. Thanks!
#include <iostream>
using std::cout; using std::cin; using std::endl;
using std::string;
class SomeClass {
public:
SomeClass(int newNum, string newString) { num=newNum; str = newString; }
SomeClass& operator=(const SomeClass& rh) {
string newVal(rh.getStr());
str = newVal;
}
void setStr(string newString) { str = newString; }
const string getStr() { return str; }
string toString() { return str+str; }
private:
string str;
int num;
};
int main() {
SomeClass a(5, "five");
SomeClass b(3, "three");
cout << a.toString() << endl << b.toString() << endl;
a=b;
cout << a.toString() << endl << b.toString() << endl;
}
const string getStr() { return str; }
should be
const string& getStr() const { return str; }
Otherwise you cannot call a non-const function on a const parameter of
SomeClass& operator=(const SomeClass& rh)
Note that private, public and protected visibility is at class level, not instance level. So there is no need for a getStr() function. You could write:
SomeClass& operator=(const SomeClass& rh) {
this->str = rh.str;
return *this;
}
Everything looks fine so far except that you've not included
#include <string>
You need to include this as well.
Oh I also saw that you're not returning anything from the function:
SomeClass& operator=(const SomeClass& rh) {
string newVal(rh.getStr());
str = newVal;
return *this; //DO THIS AS WELL
}
And also, rh is a const object in this function and using it, you're calling getStr() which is a non-const function which is causing the problem. So the fix is this:
const string getStr() const { return str; }
// ^^^^^ make the function const!
And alternatively, you could've written your operator= as follows:
SomeClass& operator=(const SomeClass& rh) {
str = rh.str; //no need to create a local (temporary) variable!
return *this; //DO THIS AS WELL
}
I think its better solution!
You just need to change
const string getStr() { return str; }
to
const string getStr() const { return str; } //the 2nd const make getStr() a const member function
^^^^
This is because const object can only call const member function and you were trying to doing this:
SomeClass& operator=(const SomeClass& rh) { //here you declared rh to be const
//so in order to call getStr() from rh, you need declare getStr function to be const
string newVal(rh.getStr());
str = newVal;
return *this;
}
So your class could simply look like this:
class SomeClass {
public:
SomeClass(int newNum, string newString):num(newNum), str(newString) {/* Empty */}
SomeClass& operator=(const SomeClass& rh) {
str=rh.str;
return *this;
}
string toString() { return str+str; }
private:
string str;
int num;
};
Related
I have created a basic string class and i want to assign it some value
but the problem is that I have to do something like this...
string str("Hello");
Isn't there a way so i can do it something like....
string str = "Hello";
Like how c++ std:: defined types (vector,string etc) do?
And also I want that instead of typing std::cout << str.val() I can do std::cout << str; to access its value and same for modifying (or updating) it.
#include<iostream>
class string
{
private:
char* str; // An uninitialized string
public:
string(char* text) // Constructor which takes a string
{
str = text;
}
char* val() // used to access the value stored in String
{
return str;
}
void update(char* string2) // used to update the value of string
{
str = string2;
}
};
int main()
{
string myStr("Hello World\n"); //initializes a string object
std::clog << myStr.val();
myStr.update("Bye World\n"); //updates the value of myStr
std::clog << myStr.val();
}
Thanks to whoever answers....
you can do this using overloaded operators
string& operator= ( const string & );
string& operator= ( const char *);
You can Overload the operators = and << like Below
Overloading the = Operator
string& operator = (char * text)
{
this->str=text;
return *this;
}
Overloading the << Operator
friend std::ostream& operator << (std::ostream& outputstream,string& thestr)
{
outputstream<<thestr.val();
return outputstream;
}
So the Overall will be like below
#include<iostream>
class string
{
private:
char* str; // An uninitialized string
public:
string(char* text) // Constructor which takes a string
{
str = text;
}
char* val() // used to access the value stored in String
{
return str;
}
void update(char* string2) // used to update the value of string
{
str = string2;
}
string& operator = (char * text)
{
this->str=text;
return *this;
}
friend std::ostream& operator << (std::ostream& outputstream,string& thestr)
{
outputstream<<thestr.val();
return outputstream;
}
};
int main()
{
string myStr="Hello World\n"; //initializes a string object
std::clog<<myStr;
myStr="Bye World\n"; //updates the value of myStr
std::clog << myStr;
}
You need to implement these operators ('=' and '<<') manually. See https://en.cppreference.com/w/cpp/language/operators (or search for c++ operator overloading in case of broken links)
In this case, you can add this code to your string class.
// Allow assignment with another `string`
string& operator=(const string& other) {
str = other.str;
return *this;
}
// This is optional. Without this, the previous `operator=` will be called
// with `other` implicitly converted to a `string`
string& operator=(char* other) {
str = other;
return *this;
}
// With the `friend` keyword, you can write a global function inside a class
friend std::ostream& operator<<(std::ostream& os, const string& obj)
{
return os << obj.str;
}
I have code like below and I need to write a global function overloading the addition operator for objects of this class so that the resulting object represents the concatenation of two strings separated by the '+' sign. Can someone help me?
class A {
char* str;
// ...
};
Such operator should have access to content of class and to create a new instance of class A which it returns. Assuming there is no public interface to access str such operator have to be a friend function with signature similar to one below
class A {
char* str;
// ...
friend A operator+ (const A& arg1, const A& arg2)
{
A temp{arg1}; // assuming that A have a copy constructor
// perform concatenation of temp and arg2 here
return temp;
}
};
Try something like this:
class A
{
char* str;
// ...
public:
A(const char *s = nullptr) : str(nullptr) {
if (s) {
str = new char[strlen(s)+1]);
strcpy(str, s);
}
}
A(const A &src) : A(src.str) {}
A(A &&src) : str(src.str) { src.str = nullptr; }
~A() { delete[] str; }
A& operator= (A rhs) {
A temp{std::move(rhs)};
std::swap(str, temp.str);
return *this;
}
friend A operator+ (const A& arg1, const A& arg2)
{
A temp;
temp.str = new char[strlen(arg1.str)+1+strlen(arg2.str)+1];
sprintf(temp.str, "%s+%s", arg1.str, arg2.str);
return temp;
}
};
That being said, you really should use std::string instead of char*:
class A
{
std::string str;
// ...
public:
A(const std::string &s = "") : str(s) {}
friend A operator+ (const A& arg1, const A& arg2)
{
return A{arg1.str + "+" + arg2.str};
}
};
These are sources that work:
MyString.h
#pragma once
class CMyString {
public:
CMyString();
CMyString(const CMyString &rhs);
CMyString(const char* param);
~CMyString();
private:
char* m_pszData;
int m_nLength;
public:
int setString(const char* pszParam);
const char* getString() const;
void release();
CMyString& operator=(const CMyString &rhs);
operator char*() const;
};
MyString.cpp
#include "MyString.h"
#include <iostream>
#include <cstring>
CMyString::CMyString() : m_pszData(NULL), m_nLength(0) {
}
CMyString::CMyString (const CMyString &rhs) : m_pszData(NULL), m_nLength(0) {
this->setString(rhs.getString());
}
CMyString::CMyString (const char* pszParam) : m_pszData(NULL), m_nLength(0) {
setString(pszParam);
}
CMyString::~CMyString() {
release();
}
int CMyString::setString(const char* pszParam) {
release();
if(pszParam == NULL)
return 0;
m_nLength = strlen(pszParam);
if(m_nLength == 0)
return 0;
m_pszData = new char[m_nLength + 1];
strncpy(m_pszData, pszParam, m_nLength);
return m_nLength;
}
const char* CMyString::getString() const {
return m_pszData;
}
void CMyString::release() {
if(m_pszData != NULL)
delete[] m_pszData;
m_pszData = NULL;
m_nLength = 0;
}
CMyString &CMyString::operator = (const CMyString &rhs) {
if(this != &rhs)
this->setString(rhs.getString());
return *this;
}
CMyString::operator char*() const { return m_pszData; }
StringCtrlSample.cpp
#include "MyString.h"
#include <iostream>
using namespace std;
void testFunc(const CMyString &strParam) {
cout << strParam << endl;
}
int main(int argc, char *argv[]) {
CMyString strData("Hello");
cout << strData.getString() << endl;
::testFunc(strData);
::testFunc(CMyString("World"));
return 0;
}
I tried operator overloading about char*() without "const" keyword at MyString.h and MyString.cpp but printed error at compiling. ex) operator char*();
Can someone explain me the difference about adding "const" keyword at the end of char*()?
In this function:
void testFunc(const CMyString &strParam) {
cout << strParam << endl;
}
strParam is a const-reference to a CMystring, so you can only call const-qualified method on it:
// Not const-qualified overload
operator char*()
// const-qualified overload
operator char*() const
Within a const-qualified method, you cannot modify non-mutable attributes or call non-const methods, which guarantees that your object is not "modified" (at least it should not be from an external point of view).
Note that you should likely convert to const char* from the const-qualified method, otherwise it would be possible to do this:
void testFunc(const CMyString &strParam) {
// I am modifiying the underlying char array of const variable
static_cast<char*>(strParam)[0] = '\0';
}
So your conversion operator should be:
operator const char*() const;
Adding the const keyword at the end of a method forbids it to change any member values or call any non-const methods.
The only exception are mutable values, which can always be modified.
class A
{
int i1;
mutable int i2;
public:
void m() const
{
// i1 = 5 <- error
i2 = 5 // <- ok
}
}
Why is this causing segmentation fault?
#include <iostream>
struct A
{
std::string str;
A(std::string const& pstr) : str(pstr)
{}
operator std::string const&() const { return str; }
};
bool operator==(A const& a, A const& b)
{ return std::string(a) == b; }
int main()
{
A a1("hola"), a2("adios");
std::cout << (a1 == a2) << std::endl;
return 0;
}
After all, the member str is still alive when doing the conversion.
http://coliru.stacked-crooked.com/a/e7453471bc1af93e
You have an recursive call to your operator==. Your constructor of A defines an implicit cast of string to A. To not allow that, add explicit to the constructor, but then you are missing a operator== for string and A;
Just edited your code and it worked for me:
return std::string(a) == std::string(b);
I have the following code:
class B {
public:
B(const std::string& str):m_str(str) { }
B(const B& b):m_str(b.m_str) { }
B& operator=(const B& b) { m_str = b.m_str; return *this; }
private:
std::string m_str;
};
main()
{
std::string a = "abc";
B b(a);
}
class B belongs to the client. I can't change it and I may not even know its specific name ("B" is simply an example); all I know is there's a client class that accepts a std::string for its constructor. Now I want to change the type of "a" in main() from std::string to A, as defined below:
class A {
public:
A(const std::string& str):m_str(str) { }
A(const char *str):m_str(str) { }
A(const A& a):m_str(a.m_str) { }
A& operator=(const A& a) { m_str = a.m_str; return *this; }
private:
std::string m_str;
};
So now I have a new main():
main()
{
A a = "abc";
B b(a);
}
This can't compile properly as it is. Is there anything I can do without changing the new main()? I can't change class B, and class A should not reference class B in any way.
Thanks!
add an cast operator
class A {
public:
....
operator const std::string()
{
return m_str;
}
Add user-defined conversion function as:
class A
{
public:
//other code
operator std::string()
{
return m_str;
}
//...
};
This allows you write these:
B b(a); //which is what you want
std::string s = a; //this is also okay;
void f(std::string s) {}
f(a); //a converts into std::string, by calling user-defined conversion function
However you cannot write this:
const A ca("hi");
std::string s = ca; //error
Its because ca is a const object which cannot invoke non-const user-defined conversion function.
Note the user-defined conversion function returns the string by value which means it returns a copy of the original string. So you may want to avoid this by defining it as:
operator const std::string &() const
{
return m_str;
}
Now, with this you can write this:
const A ca("hi");
std::string s = ca; //ok
A a("hi");
std::string s = a; //ok
How about
int main() //note the correct declaration of main
{
A a = "abc";
B b(a.GetString()); //GetString returns m_str;
}
By the way, all your definitions of copy constructors and copy-assignment operators coincide with the definitions the compiler would have auto-generated for you.
Edit
I just noticed your constraint that main() should not change. In this case you can define a conversion function from A to string (but it can be dangerous, note).
class A
{
...
operator std::string() const {return m_str; }
};
Add this to class A:
operator std::string () { return m_str; }