C++ 类

类的定义:

class Box
{
   public:
      double length;   // 盒子的长度
      double breadth;  // 盒子的宽度
      double height;   // 盒子的高度
};
  • 创建类的对象
Box Box1;          // 声明 Box1,类型为 Box
Box Box2;          // 声明 Box2,类型为 Box
  • 类的成员函数:所有成员函数都是内联函数

内联函数inline:引入内联函数的目的是为了解决程序中函数调用的效率问题,这么说吧,程序在编译器编译的时候,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体进行替换,而对于其他的函数,都是在运行时候才被替代。这其实就是个空间代价换时间的i节省。所以内联函数一般都是1-5行的小函数。

// 类内部定义
class Box
{
   public:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
   
      double getVolume(void)
      {
         return length * breadth * height;
      }
};

// 类外部定义
double Box::getVolume(void)
{
    return length * breadth * height;
}
  • 类访问修饰符
    • public:共有成员 公有成员在程序中类的外部是可访问的。您可以不使用任何成员函数来设置和获取公有变量的值
    • private:私有成员 私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员,不能被派生类访问。默认情况下,类的所有成员都是私有的。
    • protected:受保护成员 保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的。
class Box
{
    double width // 私有变量;
    public:
        double getWidth( void )
        {
            return width // 可以访问
        }
}
  • 类的继承
  public成员 protected成员 private成员
public继承 public protected private
protected继承 private private private
private继承 private private private
// 类的继承
class B : public A{
    // new stuff
    // A的成员属性保持不变
    // A的private成员无法被B访问
}
    • 一个派生类继承了所有的基类方法,但下列情况除外:
      • 基类的构造函数、析构函数和拷贝构造函数。
      • 基类的重载运算符。
      • 基类的友元函数。
    • 多继承:
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};
    • 虚拟继承:多继承(环状继承),A->D, B->D, C->(A,B)时使用,防止D创建两个对象
class D{......};
class B: virtual public D{......};
class A: virtual public D{......};
class C: public B, public A{.....};
    • 类的运算符重载:
// 以类的成员函数定义
Box operator+(const Box&);

// 类的非成员函数
Box operator+(const Box&, const Box&);
// 隐式类型转换
operator int()  // 在将类赋值到int型变量时触发


// 赋值运算符重载
void operator=(const Distance &D )
{ 
    feet = D.feet;
    inches = D.inches;
}


// 一元运算符重载
// 重载负运算符( - )
Distance operator- ()  
{
    feet = -feet;
    inches = -inches;
    return Distance(feet, inches);
}
// ++ 或 --
// 重载前缀递增运算符( ++ )
Time operator++ ()  
{
    ++minutes;          // 对象加 1
    if(minutes >= 60)  
    {
        ++hours;
        minutes -= 60;
    }
    return Time(hours, minutes);
}
// 重载后缀递增运算符( ++ )
// 因为符号一样,所以给后置版本加一个int形参作为区分,形参不会用到
Time operator++( int )         
{
    // 保存原始值
    Time T(hours, minutes);
    // 对象加 1
    ++minutes;                    
    if(minutes >= 60)
    {
        ++hours;
        minutes -= 60;
    }
    // 返回旧的原始值
    return T; 
}


// 二元运算符
// 重载 + 运算符,用于把两个 Box 对象相加
Box operator+(const Box& b)
{
    Box box;
    box.length = this->length + b.length;
    box.breadth = this->breadth + b.breadth;
    box.height = this->height + b.height;
    return box;
}
// 使用友元函数时有序的两个对象可以转换顺序相加
// 首先是一个类成员重载
// 这个函数只能允许类对象加数字,不允许数字加类对象
A A::operator+(const int b)
{
    return A(a+b);
}
// 然后用一个友元函数允许数字加类对象
// friend A operator+(const int b, A obj);
A operator+(const int b,  A obj)
{
    return obj+b;//友元函数调用第二个重载+的成员函数  相当于 obj.operator+(b); 
}


// 下标运算符 [] 重载
int& operator[](int i)
{
    if( i > SIZE )
    {
        cout << "索引超过最大值" <<endl; 
        // 返回第一个元素
        return arr[0];
    }
    return arr[i];
}


// 类成员访问运算符 -> 重载
// 如果使用了 -> 运算符,返回类型必须是指针或者是类的对象。
  • 构造函数:它会在每次创建类的新对象时执行

    构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。

Line::Line(void)
{
    cout << "Object is being created" << endl;
}

// 在声明类的实例时执行
// 带参数的构造函数
Line::Line( double len)
{
    length = len;
    cout << "Object is being created, length = " << len << endl;
}

// 声明
Line line(10.0
  • 类的析构函数:它会在每次删除所创建的对象时执行。

    析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

Line::~Line(void)
{
    cout << "Object is being deleted" << endl;
}
  • 类的拷贝构造函数:它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。
    • 通过使用另一个同类型的对象来初始化新创建的对象。
    • 复制对象把它作为参数传递给函数。
    • 复制对象,并从函数返回这个对象。
Line::Line(const Line &obj)
{
    cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
    ptr = new int;
    *ptr = *obj.ptr; // 拷贝值
}
  •  类的友元函数:类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数
class Box
{
   double width;
public:
   friend void printWidth( Box box ); // 友元函数
   void setWidth( double wid );
};

// 请注意:printWidth() 不是任何类的成员函数
void printWidth( Box box )
{
   /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
   cout << "Width of box : " << box.width <<endl;
}

 Box box;
 printWidth( box ); // 顺利访问box实例的私有变量width
  • this指针:每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。
class Box
{
   public:
      // 构造函数定义 略
      double Volume()
      {
         return length * breadth * height;
      }
      int compare(Box box)
      {
         // this是本类的对象的指针
         return this->Volume() > box.Volume();
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};
  • 指向类的指针:
Box *ptrBox;  // 声明指针
ptrBox = &Box1;  // 保存对象地址
cout << ptrBox->Volume() << endl;  // 访问类的成员
  • 静态成员:使用 static 关键字来把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。

    不同的对象可以访问和修改同一个静态成员。

class Box
{
   public:
      static int objectCount;  // 静态成员
};

// 初始化类 Box 的静态成员(必须有)
int Box::objectCount = 0;

/* 静态成员变量在类中仅仅是声明,没有定义,所以要在类的外面定义,实际上是给静态成员变量分配内存。如果不加定义就会报错,初始化是赋一个初始值,而定义是分配内存。*/
  • 通过把类成员函数声明为const   以表明它们不修改类对象
1 class MyClass  
2 {   
3   public:   
4       int GetData(int Id,int Type,char* pData)const;  
5 }  
  •  多态: 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
    • 用父类指针指向子类对象,调用函数成员会被编译器自动设置为基类中的版本(静态多态,静态链接,早绑定
    • 对父类函数使用virtual关键字,可允许不同的子类使用不同的函数实现(动态链接,后期绑定
  • 虚函数:在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
    • 纯虚函数:在基类中不对虚函数给出有意义的实现
virtual int area() = 0;
// = 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数。

 

 

posted @ 2018-07-19 15:03  C2H5OHlife  阅读(137)  评论(0编辑  收藏  举报