How to create operator overload? - c++

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};
}
};

Related

Class conversion not working as expected

I defined simple conversion method
operator string() { return /*...*/; }
When I call it directly
obj.operator string()
It works fine, but when I call it this way ...
(string)obj
Result is empty string.
What's going on? (I'm using gcc c++14) (Can post code If needed)
Class
class String : public std::string {
std::string str_;
public:
String() {};
String(const String & s) {
str_ = std::string(s.str_);
};
String(String && s) {
str_ = std::string(s.str_);
};
String(const string & s) {
str_ = std::string(s);
};
String(const char * s) {
str_ = std::string(s);
};
char & operator[](size_t i) {
return str_[i];
};
String & operator=(const String & str) {
if (this != &str) {
str_ = str.str_;
}
return *this;
};
String & operator=(String && str) {
if (this != &str) {
str_ = str.str_;
}
return *this;
};
bool operator==(const String & str) {
return str_ == str.str_;
};
bool operator!=(const String & str) {
return str_ != str.str_;
};
operator string() {
return str_;
};
};
The problem is that your class is deriving from std::string.
Remove the : public std::string part and the conversion operator will be used.
You class is already declaring an std::string member (so it uses the "has-a" approach) and doesn't need the "is-a" approach.
By the way deriving from standard library classes is almost always a bad idea (they were not designed for that).

Overloading operator= for structs, within classes

We have the following:
(pseudoish)
class MyClass
{
private:
struct MyStruct{
MyStruct operator=(const MyOtherStruct& rhs);
int am1;
int am2;
};
};
We'd like to overload the = operator in the MyClass.cpp to do something like:
MyStruct&
MyStruct::operator=(const MyOtherStruct& rhs)
{
am1 = rhs.am1;
am2 = rhs.am2;
}
However, it doesn't want to compile. We're getting an error similar to
"missing ; before &"
and
"MyStruct must be a class or namespace if followed by ::"
Is there some concept here I'm missing?
You need to move your operator= for MyStruct into the struct declaration body:
class MyClass
{
private:
struct MyStruct{
int am1;
int am2;
MyStruct& operator=(const MyOtherStruct& rhs)
{
am1 = rhs.am1;
am2 = rhs.am2;
return *this;
}
};
};
Or if that's not possible because MyOtherStruct is incomplete or don't want to clutter the class declaration:
class MyClass
{
private:
struct MyStruct{
int am1;
int am2;
MyStruct& operator=(const MyOtherStruct& rhs);
};
};
inline MyClass::MyStruct& MyClass::MyStruct::operator=(const MyOtherStruct& rhs)
{
am1 = rhs.am1;
am2 = rhs.am2;
return *this;
}
The syntax is
MyStruct& operator=(const MyOtherStruct& rhs) {
// assignment logic goes here
return *this;
}
for an operator directly within the body of MyStruct. Also note that I added the idiomatic return *this to let the assignment return a reference to this object.
EDIT in response to OP editing the question.
You can also declare the operator in the body, and define it somewhere else. In this case, the syntax is:
MyClass::MyStruct& MyClass::MyStruct::operator=(const MyOtherStruct& rhs) {
// assignment logic goes here
return *this;
}

How correctly to write a copy constructor, destructor, and assignment operator when inheriting?

This is correct?
class SearchString : public NString {
DataForSearchInString dataForSearchInString;
public:
SearchString():NString(){}
SearchString(const char * data):NString(data){}
SearchString(const SearchString & other) : NString(other), dataForSearchInString() {}
SearchString& operator=(const SearchString& other)
{
NString::operator=(other);
dataForSearchInString.setBegin(other.getBegin());
return *this;
}
// if will be classes - children or there any virtual function then need to write "virtual ~SearchString() {}" here
// Some functions
inline const int getBegin() const {return dataForSearchInString.getBegin();}
};
It seems OK, but I think you forget DataForSearchInString(other.dataForSearchInString)
class SearchString : public NString {
DataForSearchInString dataForSearchInString;
public:
SearchString():NString(){}
SearchString(const char * data):NString(data){}
SearchString(const SearchString & other) :
NString(other),
DataForSearchInString(other.dataForSearchInString) {}
^^^^^^^^^^^^^^^^^^^^^^^^^^^
SearchString& operator=(const SearchString& other)
{
NString::operator=(other);
dataForSearchInString.setBegin(other.getBegin());
return *this;
}
};

Trouble with defining my own operator...

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;
};

C++ class conversion possible?

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; }