Encapsulation Instance _c language for C + + dynamic array classes

Source: Internet
Author: User
Tags bitwise operators

Dynamic array in C + + is a dynamically allocated array of memory that can grow dynamically according to demand. To implement the encapsulation of a dynamic array class, we need to consider several issues: the use of New/delete, the memory allocation strategy, the four functions of the class (constructors, copy constructors, copy assignment operators, destructors), and the overloads of operators. Involved in a lot of knowledge, this article only do a simple introduction.

One, memory allocation policy

When you request a piece of memory for a dynamic array with new, the elements in the array are stored continuously, such as vectors and strings. When adding elements to a dynamic array, it is not possible to simply add new elements to other locations in memory if there is no room for the new element-because the elements must be continuously stored. So you have to reassign a larger chunk of memory, move the original elements from the old location to the new space, and then add new elements to free up the old memory space. If we add a new element, we perform a memory allocation and release operation once, and the efficiency will be slow.

To avoid the above costs, you must reduce the number of memory reallocation. So the strategy we're taking is that when we have to allocate new memory space, we need to allocate more memory space (usually twice times) than the new space. This allows you to add elements without having to reapply for memory space for quite some time . Note that new memory space can be allocated only when there is a compelling necessity .

Two, the four functions of class

A C + + class typically has at least four functions, namely, constructors, copy constructors, copy assignment operators, and destructors. If the class does not define the above function itself, the C + + compiler will synthesize 4 default versions for it. But often the compiler does not synthesize what we expect, and we need to define them ourselves.

1. Constructor function

The constructor of a class (constructor) is used to initialize a non-static data member of a class object, and a constructor is executed whenever the object of the class is created.

class Foo {public 
: 
  foo ();//Constructor 
  foo (string &s); 
  // ... 

The constructor has the same name as the class name and no return type. A class can contain multiple constructors (overloads) that require a distinction between the number or type of arguments. The constructor has an initialization part and a function body, and the member initialization is done before the function body executes.

2. Copy constructor

If the first parameter of a constructor is a reference to its own class type, and any additional parameters have a default value, this constructor is a copy constructor (copy constructor).

class Foo {public 
: 
  foo (); 
  Foo (const foo&); Copy constructor 
  //... 
}; 

The copy constructor defines how to initialize another object of the same type with one object. Copy initialization is usually done using copy constructors. Copy initialization occurs in the following situations:

Initializes a variable with an equal sign (=)
Passing an object as an argument to a parameter of an unreferenced type
Returns an object from a function of a return type that is not a reference type
Initializes an array of elements with a curly brace list

3. Copy assignment operator

The Copy assignment operator (copy-assignment operator) of a class is a function called operator=. Similar to any other function, it also has a return type and a list of parameters.

class Foo {public 
: 
  foo (); 
  foo& operator= (const foo&); Assignment operator 
  //... 
}; 

The copy assignment operator defines how an object is assigned to another object of the same type. An assignment operator is a member function that is also a two-dollar operator whose left operand is bound to an implicit this pointer and the right-hand operator is passed as an explicit parameter. Note: in order to be consistent with the assignment of a built-in type, the assignment operator usually returns a reference to its left-side Operation object.

4. destructor

The class's destructor (destructor) is used to free the resources used by the class object and to destroy the non-static data members of the class object, and the destructor is executed automatically whenever an object is destroyed.

Class Foo {public 
: 
  ~foo ();//destructor 
  //... 
}; 

The name of the destructor is composed of the wave number (~) plus the class name, and there is no return type. Because a destructor does not accept arguments, it cannot be overloaded. A destructor has a function body and a destructor that destroys an object by first executing the destructor body and then destroying the member in reverse order of initialization.

Overloading of operators

Overloaded operators are functions that have special names: their names are made up of keyword operator and the operator symbols that are subsequently defined. As with other functions, overloaded operators also contain return types, argument lists, function bodies, such as copy assignment operators.

When we define an overloaded operator, we must first decide whether to declare it as a member function of a class or as a normal, non-member function. Some operators must be members, while others are better as normal functions than as members:

The Assignment (=), subscript ([]), Call (()), and member Access arrow (->) operators must be members.
A composite assignment operator should generally be a member, but not necessarily, which is slightly different from the assignment operator.
An operator that changes the state of an object, or an operator that is closely related to a given type, such as an increment, decrement, dereference operator, should normally be a member.
A symmetric operator may convert an operation object at either end, such as arithmetic, equality, relationships, and bitwise operators, so they should usually be ordinary, non-member functions.
Of course, in addition to the assignment operator, we also need to define the subscript operator operator [] for the dynamic array. The subscript operator must be a member function. In order for the subscript to appear at either end of the assignment operator, the subscript operator function usually returns a reference to the element being accessed.

Iv. encapsulation of dynamic array classes

The following is an interface to the dynamic array Darray class:

Class Darray 
{ 
private: 
  double *m_data;//holding the array's dynamic memory pointer 
  int m_size;   The number of elements of an array 
  int m_max;    Memory size reserved for dynamic arrays 
private: 
  void Init ();   Initialize 
  void free ();   Free dynamic memory 
  inline bool Invalidateindex (int nindex);//judge the legality of the subscript public 
: 
  Darray ();    Default constructor 
  darray (int nsize, double dvalue = 0);//constructor, set array size, default value is Dvalue 
  darray (const darray& arr);//Copy Construction function 
  darray& operator= (const darray& arr);//Copy assignment operator 
  ~darray ();    destructor 
 
  void Print ();  Outputs an explicit value of all array elements 
  int getsize ();  Gets the size (number of elements) 
  void SetSize (int nsize) of the array, and/or resets the size of the array, if the nsize is less than the original size, truncate; otherwise, the new element is set to 0 
  double GetAt (int nindex); Gets the specified location element 
  void SetAt (int nindex,double dvalue);//Resets the value of the specified element 
  void pushback (double dvalue);//Append a new element to the end of the array 
  void deleteat (int nindex);   Deletes the element 
  void insertat (int nindex, double dvalue) at the specified location;//Insert a new element into the array 
  double operator[] (int nindex) const;< c34/>//overloaded subscript operator [] 
}; 

Here is the implementation method:

void Darray::init () {m_size = 0; 
  By default, the array does not contain elements M_max = 1; 
m_data = new Double[m_max]; 
} void Darray::free () {delete [] m_data; 
  BOOL Darray::invalidateindex (int nindex) {if (nindex>=0 && nindex<m_size) return false; 
else return true; 
}//default constructor Darray::D Array () {Init (); 
  }//Constructor Darray::D Array (int nsize, double dvalue) {if (nsize = = 0) Init (); 
    else {m_size = nsize; 
    M_max = nsize; 
    m_data = new Double[m_max]; 
  for (int i=0; i<nsize; ++i) M_data[i]=dvalue; 
  }//Copy constructor Darray::D Array (const darray& arr) {m_size = arr.m_size;//Copy Regular member */M_max = Arr.m_max;  m_data = new Double[m_max]; 
/* Copy the pointer to the content * * memcpy (m_data, Arr.m_data, m_size*sizeof (double)); }//Copy assignment operator darray& darray::operator= (const darray& arr) {if (this = = &arr)/* Self assignment/return *this 
  ; 
  M_size = arr.m_size; 
  M_max = Arr.m_max; /* Copy the right object to the temporary object before destroying the left object* * Double *m_temp = new Double[m_max]; 
  memcpy (M_temp, Arr.m_data, m_size*sizeof (double)); 
  delete [] m_data; 
 
  m_data = m_temp; 
return *this; 
//destructor Darray::~darray () {free (); //print array void Darray::P rint () {if (m_size = 0) {cout << ' error:the empty array can ' t be printed. 
    "<< Endl; 
  Exit (0); 
    else {for (int i=0; i<m_size; ++i) cout << m_data[i] << ""; 
  cout << Endl; 
}//get array size int darray::getsize () {return m_size; }//reset array size void darray::setsize (int nsize) {if (Nsize < m_size)/* Truncate/{for (int i=nsize; i<m_size ; 
  ++i) M_data[i] = 0; } if (m_size<=nsize && nsize<=m_max)/* New element set 0*/{for (int i=m_size; i<nsize; ++i) m_data 
  [I] = 0; 
    } if (Nsize > M_max)/* need to reallocate space * * {M_max = nsize; 
    Double *temp = new Double[m_max]; 
    memcpy (temp, m_data, m_size*sizeof (double)); for (iNT I=m_size; i<nsize; 
    ++i) Temp[i] = 0; 
    delete [] m_data; 
  m_data = temp; } m_size = nsize; /* Set array size///Get the specified location element double darray::getat (int nindex) {if (Invalidateindex (nindex)) {cout << 
    Error:the index of GetAt is invalid! "<< Endl; 
  Exit (0); 
return M_data[nindex]; }//sets the value of the specified location element void Darray::setat (int nindex, double dvalue) {if (Invalidateindex (nindex)) {cout <&lt ; 
    "Error:the index of SetAt is invalid!" << Endl; 
  Exit (0); 
  else {M_data[nindex] = Dvalue; }//Append a new element to the end of the array void Darray::P ushback (double dvalue) {if (M_size < M_max) {M_data[m_size] = Dvalu 
  E 
    else {M_max = m_max*2; 
    double* temp = new Double[m_max]; 
    memcpy (temp, m_data, m_size*sizeof (double)); 
    delete [] m_data; 
    m_data = temp; 
  M_data[m_size] = Dvalue; } ++m_size; 
 /* Array size plus 1*/}//Remove an element from the array void Darray::D eleteat (int nindex) { if (Invalidateindex (nindex)) {cout << "error:the index of Deleteat is invalid." << Endl; 
  Exit (0); 
    else {for (int i=nindex; i<m_size; ++i) m_data[i] = m_data[i+1]; 
    M_data[m_size-1] = 0; 
  --m_size; 
    }//Insert a new element to the specified location void darray::insertat (int nindex, double dvalue) {if (nindex<0 | | nindex>m_size) { 
    cout << "Error:the index of InsertAt is invalid!" << Endl; 
  Exit (0); 
    if (M_size < M_max)/* is not full, insert */{for (int i=m_size-1; i>=nindex;-i) m_data[i+1] = M_data[i]; 
  M_data[nindex] = Dvalue; 
    else/* Reassign space/{M_max = m_max*2; 
    double* temp = new Double[m_max]; 
    memcpy (temp, m_data, m_size*sizeof (double)); 
    delete [] m_data; 
    m_data = temp; 
    for (int i=m_size-1; i>=nindex;-i) m_data[i+1] = M_data[i]; 
  M_data[nindex] = Dvalue; } ++m_size; /* Array size plus 1/}//overloaded subscript operator [] Double Darray::operator[] (int nindex) const {if (nindex<0 | | nindex>=m_size) {cout << "error:the index in [] is inval 
    id! "<< Endl; 
  Exit (0); 
return M_data[nindex]; 
 }

After a simple test, no bugs were found yet. Perhaps the test is not comprehensive and interested readers can further test and refine the program.

Attachment: implementation of String class

A common interview question for C + + is to allow you to implement a String class, limited to time, impossible to require std::string functionality, but at least require the proper management of resources.

If you understand how the above Darray class is written, it should be easy to implement the String class. Because interviewers generally just want to check if you can correctly write constructors, destructors, copy constructors, copy assignment operators, and +, [], <<, >> operator overloads, and so on. Here is a string class interface that you can try Taker yourself to achieve:

Class string{  
  friend ostream& operator<< (ostream&,string&);//overload << operator  
  Friend istream& operator>> (istream&,string&); Overload >> operator Public  
:  
  String ();  Default constructor 
  String (const char* str);    With parameter constructor  
  String (const string& RHS);    Copy constructor  
  string& operator= (const string& RHS);  Copy assignment operator  
  String operator+ (const string& RHS) const;//operator+  
  bool operator== (const string&);       operator== 
  bool operator!= (const string&);       operator!=   
  char& operator[] (unsigned int);       Operator[]  
  size_t size () const;  
  Const char* C_STR () const; 
  ~string ();  destructor  
private:  
  char *m_data;//For saving string  
}; 

The source and test code of Darray class and string in this article can be downloaded from this site.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.