[C++] Operator overloading case – String class ③ (Overloading left shift << operator | Tips for using custom classes | Direct access to private pointer members of the class | Allocate specified size memory for the pointer and initialize it to 0)

Article directory

  • 1. Overloading the left shift << operator
    • 1. Left shift << operator function
    • 2. Overload left shift << operator
  • 2. Tips for using custom classes
    • 1. Directly access private pointer members of a class
    • 2. Allocate memory of the specified size for the pointer and initialize it to 0
  • 3. Complete code example
    • 1. String.h class header file
    • 2. String.cpp class implementation
    • 3. Test.cpp test class

1. Overload left shift << operator

1. Left shift << operator function

For left shift operator overloading, please refer to [C++] Operator Overloading ⑧ (Left shift operator overloading | Friend function/member function to implement operator overloading | Class objects use left shift operator) Blog;

The left shift operator is used in the cout << s1 << endl statement to output the s1 object to the cout standard output stream. This is

2. Overload left shift << operator

Use global function to implement left shift operator << overload:

  • First, write the function name, cout << s1 overloads the left shift operator, The function name rule is " operate " Follow the operator to be overloaded, the function name is operate<<;
operate<<
  • Then, Write the function parameters according to the operands, Parameters are generally references to objects; < /font>
    • cout << s1 The left operand is ostream cout standard output stream, and the parameter is a reference type;
    • cout << s1 The right operand is a String s class object, and the parameter is a reference type;
operator<<(ostream & amp; out, String & amp; s)
  • Then, Perfect the return value according to the business, The return value can be a reference/pointer/element; return void here That's it; returns ostream & amp; reference type to support chain calls cout << s1 << endl;
ostream & amp; operator<<(ostream & amp; out, String & amp; s)
  • Finally, implement the function body, write specific operator operation business logic;
// Implement String left shift operator overloading in global function
//Return ostream & reference type to support chain calls cout << s1 << endl;
ostream & amp; operator<<(ostream & amp; out, String & amp; s)
{
cout << "Call overload left shift << operator function ostream & amp; operator<<(ostream & amp; out, String & amp; s)" << endl;

// Output the data pointed to by the m_p pointer of the String object to the out output stream in the function body
out << s.m_p << endl;

// The return value also needs to be used as an lvalue
return out;
}

At the same time, the above function must be declared as a friend function of the String class in the String class;

class String
{<!-- -->
// Use global function to implement left shift operator << overloading
// Declare the global function as a friend function of String
friend ostream & amp; operator<<(ostream & amp; out, String & amp; s);
}

2. Tips for using custom classes

1. Directly access private pointer members of the class

During development, a class class was customized, which defined member variables of pointer type;

Generally, member variables must be declared private;

If you want to use private pointer variables directly,

Private members can be obtained through public functions;

class String
{<!-- -->
public:
// Get private member char* m_p
char*str()
{<!-- -->
return this->m_p;
}

// Get private member int m_len
intlen()
{<!-- -->
return this->m_len;
}

private:
// String length, excluding '\0'
//Memory space size = string length + 1
int m_len;

//String pointer, pointing to the string in the heap memory
char* m_p;
};

2. Allocate the specified size memory for the pointer and initialize it to 0

In the parameterized constructor, a parameter of type int is received, which represents the size of the string;

If the parameter is 0, an empty string is created. The size of the memory space pointed to by the pointer is 1, and only one \0’ character is stored, indicating the end of the string;

If the parameter is greater than 0, allocate a memory space of this size + 1 for the string pointer, and then assign this memory space to 0;

Code example:

//Constructor with parameters, receives int type value, indicating the size of the string
String::String(int len)
{<!-- -->
if (len == 0)
{<!-- -->
//Construct an empty string by default, the length of the string is 0
// However, the size of the memory space pointed to by the string pointer is 1, and the content is '\0'
this->m_len = 0;

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
this->m_p = new char[this->m_len + 1];

//Copy the empty string to the memory pointed to by m_p
strcpy(this->m_p, "");
}
else
{<!-- -->
// Get the length of the incoming string
// However, the size of the memory space pointed to by the string pointer needs + 1, and the content is '\0'
this->m_len = len;

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
this->m_p = new char[this->m_len + 1];

//Set the memory space to 0 content
memset(this->m_p, 0, this->m_len);
}
};

3. Complete code example

1. String.h class header file

#pragma once

#include "iostream"
using namespace std;

class String
{<!-- -->
public:
//Default parameterless constructor
String();

// Constructor with parameters, receives a char* type string pointer
String(const char* p);

// Constructor with parameters, receiving int type value, indicating the size of the string
String(int len);

//Copy constructor, use String object to initialize object value
String(const String & s);

// destructor
~String();

public:
// Overload the equal sign = operator, when the right operand is a String object
String & amp; operator=(const String & amp; s);

// Overload the equal sign = operator, when the right operand is a string constant value
String & amp; operator=(const char* p);

// Overload the array subscript [] operator
char & amp; operator[](int i);

// Use global function to implement left shift operator << overloading
// Declare the global function as a friend function of String
friend ostream & amp; operator<<(ostream & amp; out, String & amp; s);

public:
// Get private member char* m_p
char* str();

// Get private member int m_len
int len();

private:
// String length, excluding '\0'
//Memory space size = string length + 1
int m_len;

//String pointer, pointing to the string in the heap memory
char* m_p;
};

2. String.cpp class implementation

//Use strcpy function to report an error
// error C4996: 'strcpy': This function or variable may be unsafe.
// Consider using strcpy_s instead.
// To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
// See online help for details.
#define _CRT_SECURE_NO_WARNINGS

#include "String.h"

//Default parameterless constructor
String::String()
{
//Construct an empty string by default, the length of the string is 0
// However, the size of the memory space pointed to by the string pointer is 1, and the content is '\0'
m_len = 0;

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
m_p = new char[m_len + 1];

//Copy the empty string to the memory pointed to by m_p
strcpy(m_p, "");

cout << "Call the parameterless constructor" << endl;
}

// Constructor with parameters, receives a char* type string pointer
String::String(const char* p)
{
if (p == NULL)
{
//Construct an empty string by default, the length of the string is 0
// However, the size of the memory space pointed to by the string pointer is 1, and the content is '\0'
this->m_len = 0;

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
this->m_p = new char[this->m_len + 1];

//Copy the empty string to the memory pointed to by m_p
strcpy(this->m_p, "");
}
else
{
// Get the length of the incoming string
// However, the size of the memory space pointed to by the string pointer needs + 1, and the content is '\0'
this->m_len = strlen(p);

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
this->m_p = new char[this->m_len + 1];

//Copy the string to the memory pointed to by m_p
strcpy(this->m_p, p);
}
cout << "Call parameterized constructor" << endl;
}

// Constructor with parameters, receiving int type value, indicating the size of the string
String::String(int len)
{
if (len == 0)
{
//Construct an empty string by default, the length of the string is 0
// However, the size of the memory space pointed to by the string pointer is 1, and the content is '\0'
this->m_len = 0;

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
this->m_p = new char[this->m_len + 1];

//Copy the empty string to the memory pointed to by m_p
strcpy(this->m_p, "");
}
else
{
// Get the length of the incoming string
// However, the size of the memory space pointed to by the string pointer needs + 1, and the content is '\0'
this->m_len = len;

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
this->m_p = new char[this->m_len + 1];

//Set the memory space to 0 content
memset(this->m_p, 0, this->m_len);
}
};

//Copy constructor, use String object to initialize object value
String::String(const String & s)
{
//Copy string length
// Note: The size of the memory space pointed to by the string pointer needs to be + 1, and the content is '\0'
this->m_len = s.m_len;

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
this->m_p = new char[this->m_len + 1];

//Copy the string to the memory pointed to by m_p
strcpy(this->m_p, s.m_p);

cout << "Call copy constructor" << endl;
}

// destructor
String::~String()
{
if (this->m_p != NULL)
{
//Memory previously allocated using new
// To release memory, you need to use delete
//Memory allocated using malloc needs to be released using free
delete[] this->m_p;

// Set the pointer to null to avoid wild pointers.
this->m_p = NULL;

//Set the string length to 0
this->m_len = 0;
}
}

// Overload the equal sign = operator, when the right operand is a String object
String & amp; String::operator=(const String & amp; s)
{
// First process the memory allocated by this object
if (this->m_p != NULL)
{
//Memory previously allocated using new
// To release memory, you need to use delete
//Memory allocated using malloc needs to be released using free
delete[] this->m_p;

// Set the pointer to null to avoid wild pointers.
this->m_p = NULL;

//Set the string length to 0
this->m_len = 0;
}

//Copy string length
// Note: The size of the memory space pointed to by the string pointer needs to be + 1, and the content is '\0'
this->m_len = s.m_len;

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
this->m_p = new char[this->m_len + 1];

//Copy the string to the memory pointed to by m_p
strcpy(this->m_p, s.m_p);

cout << "Call the overloaded equal sign = operator function String & amp; String::operator=(const String & amp; s)" << endl;

return *this;
}

// Overload the equal sign = operator, when the right operand is a string constant value
String & String::operator=(const char* p)
{
// First process the memory allocated by this object
if (this->m_p != NULL)
{
//Memory previously allocated using new
// To release memory, you need to use delete
//Memory allocated using malloc needs to be released using free
delete[] this->m_p;

// Set the pointer to null to avoid wild pointers.
this->m_p = NULL;

//Set the string length to 0
this->m_len = 0;
}

//Copy string length
// Note: The size of the memory space pointed to by the string pointer needs to be + 1, and the content is '\0'
this->m_len = strlen(p);

// Use the new keyword to allocate memory for the char* m_p; pointer
// For basic data types new is equivalent to malloc
this->m_p = new char[this->m_len + 1];

//Copy the string to the memory pointed to by m_p
strcpy(this->m_p, p);

cout << "Call the overloaded equal sign = operator function String & amp; String::operator=(const char* p)" << endl;

return *this;
}

// Overload the array subscript [] operator
char & String::operator[](int i)
{
cout << "Call overloaded subscript [] operator function char & amp; String::operator[](int i)" << endl;

// Directly return the corresponding i index character
return this->m_p[i];
}

// Get private member char* m_p
char* String::str()
{
return this->m_p;
}

// Get private member int m_len
int String::len()
{
return this->m_len;
}

// Implement String left shift operator overloading in global function
//Return ostream & reference type to support chain calls cout << s1 << endl;
ostream & amp; operator<<(ostream & amp; out, String & amp; s)
{
cout << "Call overload left shift << operator function ostream & amp; operator<<(ostream & amp; out, String & amp; s)" << endl;

// Output the data pointed to by the m_p pointer of the String object to the out output stream in the function body
out << s.m_p << endl;

// The return value also needs to be used as an lvalue
return out;
}

3. Test.cpp test class

#include "iostream"
using namespace std;

//Import custom String class
#include "String.h"

int main() {<!-- -->

//Call the parameterless constructor
String s1;

// Call the parameterized constructor
String s2("Tom");

// Call the copy constructor
String s3 = s2;

//Call the overloaded equal sign operator function, the right operand is a String object
s1 = s2;

//Call the overloaded equal sign operator function, the right operand is a string constant value, char* pointer type
s3 = "Jerry";

// Call the overloaded subscript operator function
char c = s3[3];

// Call the overloaded left shift operator function
cout << s3 << endl;

//The console pauses, press any key to continue execution backwards
system("pause");

return 0;
}
syntaxbug.com © 2021 All Rights Reserved.