天天看点

类的成员函数组成_C++

类的构造函数

    • 类的基本成员函数
    • 类的构造函数
    • 类的拷贝构造函数
    • 类的拷贝赋值函数
    • string类_实现实例

类的基本成员函数

  • 类的成员函数一般包括:构造函数,析构函数,拷贝构造函数,赋值函数;
  • 每个类只有一个析构函数和一个赋值函数;
  • 但是可以有很多构造函数(一个为拷贝构造函数,其他为普通构造函数;
  • 对于一个类String,如果不编写上述四个函数,c++编译器将自动为String产生四个默认的函数,即:
String(void)                                //默认无参数构造函数
String(const String& str)                   //默认拷贝构造函数
~String(void);                              //默认的析构函数
String & operator = (const String& str);    //默认的赋值函数
           
// 声明一个类String如下
class String {
    public:
       String(const char* str=NULL);      // 构造函数
       ~String();                         // 析构函数
       String(const String& others);      // 拷贝构造函数
       String& operator=(const String& others);   // 赋值函数
       void show();           // 普通成员函数
    private:
       char *data;
};
           
补充:C++中,变量的引用
int&  r = i;
   double& s = d;
           
& 读作引用。因此,第一个声明可以读作 “r 是一个初始化为 i 的整型引用”,第二个声明可以读作 “s 是一个初始化为 d 的 double 型引用”。

类的构造函数

  • 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行;
  • 类的构造函数实则为函数的重载;
  • 构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void;
  • 构造函数可用于为某些成员变量设置初始值;
  • 默认的构造函数没有任何参数,但如果需要,构造函数也可以带有参数。这样在创建对象时就能直接给对象赋初始值;
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line(double len);            // 带有参数的构造函数
   private:
      double length;
};
// 成员函数定义,包括构造函数
Line::Line( double len)
{
    cout << "Object is being created, length = " << len << endl;
    length = len;
}
           
  • 使用初始化列表来初始化字段
Line::Line( double len): length(len)
{
    cout << "Object is being created, length = " << len << endl;
}

//  上面的语法等同于如下语法:
Line::Line( double len)
{
    length = len;
    cout << "Object is being created, length = " << len << endl;
}
           

类的拷贝构造函数

  1. 拷贝构造函数是一种特殊的构造函数,拷贝构造函数的函数名与类名相同;
  2. 要求参数必须本类型的一个引用变量,是否是const无限制;
// 类 string
String(const String& others);  // 形式1
String(String& others);        // 形式2
String(String others);         // 形式3

           

形式1是最常见的构造函数声明,这也是最好的书写方式;

形式2也是正确的,只是没有const来保护形参;

形式3错误,编译错误,因为会导致递归调用导致堆栈溢出,所以编译器直接拒绝,VS中的报错信息为:error C2333: “TestClass::TestClass”: 函数声明中有错误;跳过函数体。

类的拷贝赋值函数

  1. 拷贝赋值函数的函数名是由关键字 operator 和 = 运算符符号构成;
  2. 对于返回值和参数类型没有限制;
  3. 返回值可以为返回空、返回对象、返回对象的引用、返回常引用;
  4. 参数可以为对象、引用、常量引用。
// 类 TestClass
TestClass& operator = (const TestClass&);          // 形式1
TestClass& operator = (TestClass&);                // 形式2
TestClass& operator = (TestClass);                 // 形式3
const TestClass& operator = (const TestClass&);    // 形式4
const TestClass& operator = (TestClass&);          // 形式5
const TestClass& operator = (TestClass);           // 形式6
void operator = (const TestClass&);                // 形式7
void operator = (TestClass&);                      // 形式8
void operator = (TestClass);                       // 形式9
TestClass operator = (const TestClass&);           // 形式10
TestClass operator = (TestClass&);                 // 形式11
TestClass operator = (TestClass);                  // 形式12
           

形式1是最常见的拷贝赋值函数的声明方式,也是最好的书写方式;

其余形式也都是正确的;

string类_实现实例

#include<iostream>
using namespace std;

// string类的声明
class String
{
 public:
        String(const char* str=NULL);   //普通构造函数
        Strng(const String &other);     //拷贝构造函数
        String & operator=(const String &other);  //赋值函数
        ~String(void);                  //析构函数
 public:
        char& operator[];       // 运算符[]的重载
        bool operator==(const String& s1,const String& s2 );    // 运算符==的重载
        String & operator+=(const String &str);  //本身相加,返回this
        String & operator+(const String &s1,const String &s2) //两个String相加
        friend ostream& operator<<(ostream&out,String& s);
        friend istream& operator>>(iostream&in,String& s); 
 private:
        char *m_string ;              //保存字符串,数据封装
 };

           
// String类的定义
String::~String(void)
{
  cout<<"destrcut"<<endl;
  if(m_string!=NULL)                   //不为空,就释放内存
 {
   delete [] m_string;
   m_string = NULL;
 }
}
 
String::String(const char* str)   //普通构造函数  str并非类的成员变量
{
 cout<<construct<<endl;
 if(str==NULL)        //如果str 为NULL,就存一个空字符串
{
  m_string=new char[1];
  *m_string ='\0';
}
  else
{
  m_string = new char[strlen(str)+1] ;   //分配空间
  strcpy(m_string,str);
}
} 
 
String::String(const String& other)   //拷贝构造函数
{
  cout<<"copy construct"<<endl;
  m_string=new char[strlen(other.m_string)+1] ; //分配空间并拷贝
  strcpy(m_string,other.m_string);
}
 
char &String::operator[](int index)
{
   return  m_string[index];
}
 
bool operator==(const String& s1,const String& s2 )
{
   if(strcmp(s1.m_string,s2.m_string)==0)
     return ture;
   return false;
}
 
String & String::operator=(const String & other)
{
cout<<"operator = funtion"<<endl ;
if(this==&other) //如果对象和other是用一个对象,直接返回本身
{
return *this;
}
delete []m_string; //先释放原来的内存
m_string = new char[strlen(other.m_string)+1];
strcpy(m_string,other.m_string);
return * this;
}
 
String & String::operator+=(const String & str)
{
 char * temp=m_string;
 m_string=new char[strlen(m_string)+strlen(str.m_string)+1];
 strcpy(m_string,temp);
 delete[]temp;
 strcat(m_string,str.m_string);
 return *this;
} 
String & String::operator+(const String & s1,const String &s2)
{
String res;
  res.m_string=new char[strlen(s1.m_string)+strlen(s2.m_string)+1];
  strcpy(res.m_string,s1.m_string);
  strcat(res.m_string,s2.m_string);
  return res;
} 
ostream& operator<<(ostream& out,String& s)
{
 for(int i=0;i<s.length();i++) 
out<<s[i]<<""; 
return out;
}
istream& operator>>(istream& in,String& s)
{ 
char p[50]; 
in.getline(p,50); 
s=p; 
return in;
}

           
int main()
{
String a("hello");     //调用普通构造函数
String b("world");     //调用普通构造函数
String c(a);          //调用拷贝构造函数
c=b;                  //调用赋值函数
return 0;
}
           

对象不存在,且没用别的对象来初始化,就是调用了构造函数;

对象不存在,且用别的对象来初始化,就是调用了拷贝构造函数;

对象存在,用别的对象来给它赋值,就是调用了赋值函数。

继续阅读