C++的一些基本特性(2)——面向对象之 类

C++相较于C最大的一个不同恐怕就在于面向对象的特性,这一特性的发挥可谓贯穿所有常用的C++库,这也是笔者特地花时间学习一下C++的原因。

C++ 类的定义:
类的基本结构如图:图片来自菜鸟教程

用类定义对象以及访问数据成员:
通过以下的实例,可以演示类的一般使用:

#include <iostream>
 
using namespace std;
 
class Box		//定义名为Box的类
{
   public:		//public是成员的访问修饰符,public的成员可以用.(点)来访问
      double length;   // 长度
      double breadth;  // 宽度
      double height;   // 高度
      // 成员函数声明,表示的就是这个类里能有啥方法(函数)
      //基本形式和一般的函数声明没什么区别
      double get(void);
      void set( double len, double bre, double hei );
};
// 成员函数定义
//在类之外,对其声明的函数进行定义,此处注意,要用特定的方法指明正在定义类里的函数
double Box::get(void)
{
    return length * breadth * height;
}
 
void Box::set( double len, double bre, double hei)
{
    length = len;
    breadth = bre;
    height = hei;
}
int main( )//……省略
{
}

C++类的详解:

一、 C++类成员函数:

C++类成员函数就是指的类所“包含”或者也许可以理解为“具有” 的功能。类成员函数把函数声明为内联函数,不论是否用inline。
言归正传,成员函数可以在类的内部(也就是类的花括号里,在声明函数的同时完成定义),也可以在类的外部,通过范围解析运算符::(也就是上面代码中的定义方式)进行定义。
值得注意的是,不论是在类内还是在类外,成员函数都是可以直接访问类成员的,也就是说不需要“类名.成员”这样访问。
关于内联:

内联指的是,当编译器发现某段代码在调用一个内联函数时,它不是去调用该函数,而是将该函数的代码,整段插入到当前位置。

二、C++ 类访问修饰符:public,private&protected
public: 公有成员在程序中类的外部是可访问的。可以不使用任何成员函数来设置和获取公有变量的值,如下所示:

// 使用成员函数设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   // 不使用成员函数设置长度
   line.length = 10.0; // OK: 因为 length 是公有的
   cout << "Length of line : " << line.length <<endl;

protected: protected(受保护)成员不可以在类之外被访问,但在派生类(即子类)中是可访问的。


class Box
{
   protected:
      double width;
};
 
class SmallBox:Box // SmallBox 是派生类,继承了基类Box的成员width
{
   public:
      void setSmallWidth( double wid );
      double getSmallWidth( void );
};
 
// 子类的成员函数,可以直接访问基类的成员
double SmallBox::getSmallWidth(void)
{
    return width ;
}
 
void SmallBox::setSmallWidth( double wid )
{
    width = wid;
}

private: 私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。即便是子类,也无法访问其父类的private成员。只有类和友元函数可以访问私有成员。默认情况下,即不用访问修饰符的情况下,成员默认为私有成员。
实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数,如下所示:

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;
      void setWidth( double wid );
      double getWidth( void );
 
   private:
      double width;
};
 
// 成员函数定义
double Box::getWidth(void)
{
    return width ;
}
 
void Box::setWidth( double wid )
{
    width = wid;
}
 
// 程序的主函数
int main( )
{
   Box box;
 
   // 不使用成员函数设置长度
   box.length = 10.0; // OK: 因为 length 是公有的
   cout << "Length of box : " << box.length <<endl;
 
   // 不使用成员函数设置宽度
   // box.width = 10.0; // Error: 因为 width 是私有的
   box.setWidth(10.0);  // 使用成员函数设置宽度
   cout << "Width of box : " << box.getWidth() <<endl;
 
   return 0;
}

在保护数据的“严格”程度上,依次是public<protected<private,这在三种继承方式中会有所体现。

三、三种继承特点:

C++有public,protected,private三种继承方式,当子类采用更“严格”的方式继承时,父类较低严格程度的成员也会“升级”其访问权限。即:

继承方式基类成员访问属性继承后成员访问属性
publicpublic,protected,privatepublic,protected,private
protectedpublic,protected,privateprotected,protected,private
privatepublic,protected,privateprivate,private,private

当继承时未指明继承方式,默认按照public继承,即成员访问属性不变。

四、构造函数和析构函数

构造函数和析构函数,是类的特殊成员函数,分别用于创建和删除对象。它们名称与类名相同不返回任何类型的值(包括void,因此不需要写返回值类型)。

构造函数:
一般情况下,构造函数如下代码所示,可以不带参数

class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();  // 这是构造函数
 
   private:
      double length;
};
 
// 成员函数定义,包括构造函数
Line::Line(void)
{
    cout << "Object is being created" << endl;//事实上,这一行业可以去掉,函数内容跟为空即可
}

为了初始化方便,构造函数常用于创建对象,并且赋初值:
赋初值有两种方式,一种是普通的赋值:

C::C( double a, double b, double c)
{
	X=a;
	Y=b;
	Z=c;
  ....
}

另一种则是使用初始化列表进行初始化

C::C( double a, double b, double c): X(a), Y(b), Z(c)
{
  ....
}

这两种初始化方法等价。

拷贝构造函数:主要作用是使用同一类中之前创建的对象初始化新创建的对象

classname (const classname &obj) {
   // 构造函数的主体
}

四、友元
友元使用friend关键字标记,可以用来标记友元类友元函数
友元函数完全不属于类,在类的外部定义,但是却可以访问类的所有成员(包括private和protected成员)。尽管友元函数的原型有需要在类的定义中指明,但是友元函数并不是成员函数
友元类的整个类和所有成员,都是友元。

友元函数的示例如下:

class Box
{
   double width;
public:
   double length;
   friend void printWidth( Box box );//友元函数
   friend class ClassTwoName;		
   void setWidth( double wid );
};

五、类的指针和this指针
类的指针与指向结构的指针类似,通过成员访问运算符->来访问成员。在类之外,即在使用类时,使用&运算符即可获得类的指针

this指针是一个特殊的指针,每一个对象都可以通过this指针来访问自己的地址。值得注意的是,this指针是所有成员函数的隐含参数,因此,在成员函数内部,this可以用来指向调用的对象。(所以实际上,在调用一个对象的成员函数时,是用该对象的地址来初始化隐式参数this)在成员函数内,可以显式的使用this获得对象的地址,并利用类指针的方式访问成员以及成员函数。

六、类的静态成员
类的静态成员,包括静态变量静态函数。它们通过static关键字来标记。
静态可以理解为,类的某种不变量 (比如,可以用来统计某个类有多少个已创建的对象),因此不论某类有多少对象,静态成员都被每个对象所共享

静态变量:静态变量的初始化比较特别,其初始化不能放在类定义中,但可以在类外,通过解析运算符:: 来访问并初始化,(如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零)。

初始化方式:

// 初始化类 Box 的静态成员
int Box::objectCount = 0;

静态成员函数: 静态成员函数与类有关,与类的任何特定对象无关,因此在对象不存在的情况也可访问,方法是:
ClassName :: static_func_name (类名::静态成员函数名)
需要注意的是以下两点:

  1. 静态成员函数只能访问静态成员变量、其他静态成员函数类外部的其他函数
  2. 静态成员函数没有 this 指针

其实上述特点也较容易理解,其是静态函数与具体的对象无关导致的。

与静态成员变量不同的是,静态成员函数可以在类定义中进行定义。

静态成员(包括变量和函数)的示例如下:

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
   	//静态成员数据的声明
      static int objectCount;
      // 构造函数定义
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // 每次创建对象时增加 1
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      //静态函数的定义
      static int getCount()
      {
         return objectCount;
      }
   private:
      double length;     // 长度
      double breadth;    // 宽度
      double height;     // 高度
};
 
// 初始化类 Box 的静态成员
int Box::objectCount = 0;
 
int main(void)
{
  //静态函数的调用,可见,其是使用类名来调用的
   // 在创建对象之前输出对象的总数
   cout << "Inital Stage Count: " << Box::getCount() << endl;
 
   Box Box1(3.3, 1.2, 1.5);    // 声明 box1
   Box Box2(8.5, 6.0, 2.0);    // 声明 box2
 
   // 在创建对象之后输出对象的总数
   cout << "Final Stage Count: " << Box::getCount() << endl;
 
   return 0;
}

至此,基本完成了C++面向对象中类的基本内容,下一部分快速地过一下继承。
晚安 😃

P.S. 有关内容大多引自菜鸟教程,在其基础上进行了总结,添加了一些自己的理解和注释

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值