#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
class Obj {
public:
Obj(int i) { cout << "Obj" << endl; }
}; // New class with int i constructor
/*
class Inner {
public:
Inner(int i) { cout << "Inner" << endl; }
}; // New class, a copy of Obj
*/
class MyStr { //: public Obj { // MyStr now inherits Obj
// Inner inner; // Inner constructs after inherited class
int length{ 0 };
char* buff{ nullptr };
public:
MyStr() : length(0), buff(nullptr) { //inner(10), Obj(10) { // Gave MyStr constructor an Obj's constructor with int i = 10 */
cout << " MyStr default constr.\n";
}
MyStr(const char* init_val) { //: Obj(10), inner(10) { // Same as above
if (init_val != nullptr && *init_val != '\0') { // , strlen(init_val) > 0
length = strlen(init_val);
buff = new char[length + 1];
strcpy(buff, init_val);
}
cout << " MyStr( char * ) constr.\n";
}
MyStr(const MyStr& other) { //: Obj(10), inner(10) {} // Same as above
if (other.length != 0) {
this->length = other.length;
buff = new char[length + 1];
strcpy(buff, other.buff);
}
}
~MyStr() { // Destructor must be virtual if the class has at least one virtual function
cout << " MyStr destr.\n";
delete[] buff;
// delete[] buff; - Will throw an exception if called twice
}
int size() { return length; }
MyStr& operator= (const MyStr& rhs) { // const MyStr& rhs = m_DerivedFromMyStr
if (this == &rhs)
return *this;
delete[] buff;
length = rhs.length;
if (rhs.length > 0) {
buff = new char[length + 1];
strcpy(buff, rhs.buff);
}
return *this;
}
friend MyStr operator+(const MyStr& s1, const MyStr& s2);
friend ostream& operator<< (ostream&, const MyStr&);
char& operator[] (int index) {
return this->buff[index];
}
};
MyStr operator+(const MyStr& s1, const MyStr& s2) { // Concatenation operator that accepts two instances of MyStr class
MyStr res; // Create the result instance of MyStr class
res.length = s1.length + s2.length; // Assign s1 and s2 instances length to result instance length
res.buff = new char[res.length + 1]; // Create a new buffer on result instance
if (s1.buff) strcpy(res.buff, s1.buff); else res.buff[0] = '\0'; // Copy s1 buffer to result buffer if not empty, else make result buffer nullptr
if (s2.buff) strcat(res.buff, s2.buff); // Append s2 buffer to result buffer if not empty
return res;
}
ostream& operator<< (ostream& os, const MyStr& s) {
return os;
}
int main() {
MyStr a; //= "Hello ";
MyStr b = "World!";
///////////////
MyStr c = a;
int j = 10;
int& i = j; // int* const pi = &j; i <=> *pi;
///////////////
MyStr c2{"10"};
//c2 = a;
///////////////
c = a + b;
cout << c << endl;
cout << c2 << endl;
cout << b.size() << endl;
return 0;
}