C++ day08 Friend Functions, Function Overloads, and Implementation String Exercises (with answers)

Day8

1. Multiple Choice Questions
1. In the description of friends, (A) is wrong.
A. Friend functions are member functions, which are explained that //Friend functions are not member functions within a class, but are declared in the class
B. Friend functions directly access private members in a class
C. Friend functions destroy encapsulation and use as little as possible
D. All member functions in a friend class are friend functions

2. The following description of the friend function is correct (C).
A. The implementation of a friend function must be defined within a class
B. Friend functions are members of classes
C. Friend function destroys class encapsulation and hiding
D. Friend functions cannot access private members of classes

3. Of the following functions, (C) is not a member function of the class.
A. Constructor B. Destructor C. Friend function D. Copy constructor

4. Friends play a role. (A)
A. Improve the efficiency of programs B. Enhance class encapsulation
C. Implementing data concealment D. Increasing the variety of member functions

5. If class A is described as a friend of class B, then (DE). (multiple choice)
A, a member of class A, a member of class B
B, a member of class B, that is, a member of class A
A member function of class A cannot access a member of class B
A member function of class D can access a member of class B
E, Class B are not necessarily friends of Class A

2. Write out the results of the following procedures

#include <iostream>

using std::endl;
using std::cout;

class B 
{  
   int y;
public:
	  friend class  A; 
};
class A
{ 
      int x;
 public:  
     A(int a,B &r, int b)  
	 {
		x=a; 
		r.y=b;
	 } 
     void Display( B & ); 
};
void A::Display(B &r)
{
    cout<<x<<" "<<r.y<<endl;
}

int main( )
{ 
    B Obj2;//An object that creates class B is obj2
    A Obj1(33,Obj2,88);//Creates an object of class A, named obj1,a is 33, x is 33 in obj2, B is 88, or r.y is 88, and y is 88 in class B
    Obj1.Display(Obj2);
	

	return 0;

} 

//33  88

3. Brief Answers

1. What is a friend? Are there any forms of friends? What are the characteristics of friends?

friend functionFriends exist in:Features of Friends
Allowing a function to be a friend of a class allows access to the public, private, protected data members of that class1 Friend Function
(2) Friends
1. One-way, non-transitive, non-inheritable
(2) Advantages: Improve the efficiency of the program.
(3) Disadvantages: Destroying class encapsulation and data transparency.

2. What is the principle of operator overloading? What are the rules?

Principles of operator overloadingrule
(1) To prevent users from overloading operators on standard types, C++ specifies that at least one of the overloaded operators must be a custom type or an enumeration type
(2) After overloading an operator, its priority and binding remain fixed.
(3) Overload does not change the usage of operators, as there were several operands, left or right, which do not change.
(4) Overloaded operator functions cannot have default parameters, otherwise the number of operators is changed.
After overloading logical operators (&, ||), they no longer have short-circuit evaluation characteristics
It is not possible to assume an operator that does not exist, such as @, $and so on.

3. How many operators can't be overloaded?

. *?:: sizeof, a total of 5

4. What are the forms of operator overload?

Forms of operator overload
1. Overload with normal function
(2) Using member function overload
3. overloading with friend function

5. What is the difference between the pre-form and post-form of the self-increasing operator? What are the return value types?

Pre-form self-increasing operatorPost-Form Self-Incrementing Operators
Formal differencesIf the ++ operator is overloaded in the usual way (with no parameters for member functions), then the overloaded version is the predecessor versionAdd an Int-type parameter to an overloaded function to tell the compiler that this is an operator postposition and that no arguments need to be passed in the actual call
return typePre++ returns reference to object, left valuePostposition++ (no reference, a copy constructor is executed once, and the copy constructor is used again to create tmp objects in defining the Complex class, and Postposition++ is slower than Preposition+) returns a local variable, a right value

4. Programming Questions
1. Describe the problem and write a Base class to output the following code as 1

int i=2;int j=7;
Base x(i);
Base y(j);
cout << (x+y == j - i) << endl;

Tip: This question examines the knowledge points overloaded by operators.

#include <iostream>

using std::cout;
using std::endl;

//Uppercase C Representation Class
class CBass{
    friend int operator+(const CBass &lhs,const CBass &rhs);
private:
    int _x;
public:
    //Destructor
    CBass(int x)
    :_x(x){}
};

int operator+(const CBass &lhs,const CBass &rhs){
    //return lhs._x+rhs._x;
    return -lhs._x+rhs._x;
}

int main()
{
    int i=2;
    int j=7;
    CBass x(i);
    CBass y(j);

    std::cout<< (x+y==j-i) <<std::endl;
    return 0;
}

[External chain picture transfer failed, source station may have anti-theft chain mechanism, it is recommended to save the picture and upload it directly (img-Q8HkcxBy-16211779046) (C:\UserskachiAppDataRoamingTyporatypora-user-imagesimage-20297.png)]

2. Implement overloading of other operators of the String class

class String 
{
public:
	String();
	String(const char *);
	String(const String &);
	~String();
	String &operator=(const String &);
	String &operator=(const char *);

	String &operator+=(const String &);
	String &operator+=(const char *);
	
	char &operator[](std::size_t index);
	const char &operator[](std::size_t index) const;
	
	std::size_t size() const;
	const char* c_str() const;
	
	friend bool operator==(const String &, const String &);
	friend bool operator!=(const String &, const String &);
	
	friend bool operator<(const String &, const String &);
	friend bool operator>(const String &, const String &);
	friend bool operator<=(const String &, const String &);
	friend bool operator>=(const String &, const String &);
	
	friend std::ostream &operator<<(std::ostream &os, const String &s);
	friend std::istream &operator>>(std::istream &is, String &s);

private:
	char * _pstr;
};

String operator+(const String &, const String &);
String operator+(const String &, const char *);
String operator+(const char *, const String &);

Specific implementation code

#include <iostream>
#include <string>
#include <string.h>

using std::cout;
using std::endl;
//using std::string;

//Capital C means this is a class
class CString{
private:
    char *_pstr;
public:
    //Constructor 1: () denotes no incoming value and creates an empty string
    CString():_pstr(nullptr){}
    //Constructor 2: Indicates that a character is passed in
    CString(const char*str){
        //If the incoming string is not empty
        if(str){
            _pstr=new char[strlen(str)+1];
            strcpy(_pstr,str);
        }
    }
    //Constructor 2: Represents an object passed into a CString class
    CString(const CString&str){
        //If the string passed in to the CString class object str is not empty
        if(str._pstr){
            _pstr = new char[strlen(str._pstr)+1];
            strcpy(_pstr,str._pstr);
        }
    }

    //Destructor
    ~CString(){
        if(_pstr){
            delete [] _pstr;
            _pstr=nullptr;
        }
    }

    //Pass in a string to the copy constructor
    //=sign overloaded function
    //In the incoming parameter &means modification
    //Use of &in incoming parameters reduces use of copy constructors and increases efficiency
    //The first &-> function will call a copy function again if it is not a reference assignment. Adding a reference will improve efficiency
    //Supplement: (parameter in copy constructor is not added & will fall into an infinite loop)
    CString &operator=(const CString&str){
        //Can't assign to yourself, delete and release the string to the left of the = sign
        if(this != &str){
            //Delete to free up the original memory first
            delete _pstr;
            _pstr=nullptr;
        }
        //If the string of the incoming object is not empty
        if(str._pstr){
            //You have to use a deep copy, or when you delete the value to the right of the previous assignment, the value to the left will lose its pointing value
            _pstr=new char[strlen(str._pstr)+1];
            strcpy(_pstr,str._pstr);
        }
        //Here * means dereference
        return *this;
    }

    //Pass in a character to the copy constructor
    CString &operator=(const char*str){
        if(str){
            _pstr=new char[strlen(str)+1];
            strcpy(_pstr,str);
        }
    }

    //Pass in a string
    CString &operator+=(const CString &str){
        size_t len=strlen(_pstr)+strlen(str._pstr)+1;
        char *tmp=new char[len]();
        strcpy(tmp,_pstr);
        strcat(tmp,str._pstr);
        delete [] _pstr;
        _pstr=tmp;//Assign the string of tmp to _ pstr
        //Returns a reference to an object, with a left value
        return *this;
    }

    //Pass in a character
    CString &operator+=(const char *str){
        size_t len=strlen(_pstr)+strlen(str)+1;
        char *tmp=new char[len]();
        strcpy(tmp,_pstr);
        strcat(tmp,str);
        delete [] _pstr;
        _pstr=tmp;//Assign the string of tmp to _ pstr
        //Returns a reference to an object, with a left value
        return *this;
    }
    
    //Returns every character in the character array
    //Size_ Features of t >=0
    //If you don't add &, the right value, or a letter, will be copied. Adding a reference returns the entity of the character array instead of a simple letter
    //You can manipulate the data inside
    //Supplement 1: (&When not added: local data, temporary objects, add as many as possible)
    //Supplement 2: Stream objects are added as much as possible
    //Overloading subscript access operators reduces the risk of crossing borders
    char &operator [](std::size_t idx){
        //len memory string length
        size_t len=strlen(_pstr);
        //Returns the appropriate character if the output character subscript is required to conform to the criteria
        if(idx<len){
            return _pstr[idx];
        }
        //Because this is a reference function, we want to return a char character with a larger life cycle than the function
        else{
            static char nullchar='\0';
            //Returning a local variable reference without static will result in an error
            return nullchar;
        }
    }
    //const before and after
    const char &operator [](std::size_t idx) const{
        //len memory string length
        size_t len=strlen(_pstr);
        //Returns the appropriate character if the output character subscript is required to conform to the criteria
        if(idx<len){
            return _pstr[idx];
        }
        //Because this is a reference function, we want to return a char character with a larger life cycle than the function
        else{
            static char nullchar='\0';
            //Returning a local variable reference without static will result in an error
            return nullchar;
        }
    }

    //Returns the size of the character array, using the object name directly. size() to get the size of the character array
    std::size_t size() const{
        return strlen(_pstr);
    }
    //Returns a C-style string
    const char* c_str() const{
        return _pstr;
    }

    //The output stream operator cannot be a member function because the first parameter of a nonstatic member function is the this pointer.
    //The first parameter of the output stream operator is the stream object, which changes the position of the operation data, so
    //Output stream operators cannot be overloaded with member functions, but can be overloaded with friend functions
    friend std::ostream &operator<<(std::ostream&os , const CString&str){
        os<<str._pstr;
        return os;
    }
    friend std::istream &operator>>(std::istream &is,CString &str){
        CString tmp;
        is>>tmp;
        if(str._pstr){
            delete [] str._pstr;
            str._pstr=nullptr;
        }
        str._pstr = new char[tmp.size()+1];
        //Assign C-style strings to str's _ pstr empty string
        strcpy(str._pstr,tmp.c_str());
        return is;
    }
    friend bool operator==(const CString&,const CString&);
    friend bool operator!=(const CString&,const CString&);
    friend bool operator>(const CString&,const CString&);
    friend bool operator<(const CString&,const CString&);
    friend bool operator<=(const CString&,const CString&);
    friend bool operator>=(const CString&,const CString&);
};

CString operator+(const CString&lhs,const CString & rhs){
    CString tmp = lhs;
    return tmp+=rhs;
}
CString operator+(const CString&lhs,const char*rhs){
    CString tmp=lhs;
    return tmp+rhs;
}
CString operator+(const char*rhs,const CString&lhs){
    CString tmp=lhs;
    return tmp+=rhs;
}

bool operator==(const CString&lhs,const CString&rhs){
    //If the same returns 0,! 0 means 1
    return !strcmp(lhs._pstr,rhs._pstr);
}
bool operator!=(const CString&lhs,const CString&rhs){
    return !(lhs==rhs);
}
bool operator<(const CString&lhs,const CString&rhs){
    return !(lhs>=rhs);
}
bool operator>(const CString&lhs,const CString&rhs){
    return !(lhs<=rhs);
}
bool operator<=(const CString&lhs,const CString&rhs){
    return strcmp(lhs._pstr,rhs._pstr)<=0;
}
bool operator>=(const CString&lhs,const CString&rhs){
    return strcmp(lhs._pstr,rhs._pstr)>=0;
}


int main()
{
    CString str1("warcraft");
    CString str2(str1);
    CString str3("buster");
    CString str4(str3);

    //
    cout<<"Output string first"<<endl;
    cout<<"str1="<<str1<<endl;
    cout<<"str2="<<str2<<endl;
    cout<<"str3="<<str3<<endl;
    cout<<"str4="<<str4<<endl;
    cout<<endl;

    //
    cout<<"Re-judge String"<<endl;
    cout<<"(str1==str2)="<<(str1==str2)<<endl;
    cout<<"(str1==str3)="<<(str1==str3)<<endl;
    cout<<"(str1<=str2)="<<(str1<=str2)<<endl;
    cout<<"(str1>str2)="<<(str1>str2)<<endl;
    cout<<endl;

    //
    CString str5;
    str5=str1;
    cout<<"str5=str1,str5="<<str5<<endl;
    cout<<endl;

 
    return 0;
}

Keywords: C++

Added by Z3roDowner on Fri, 11 Feb 2022 00:09:06 +0200