类和对象

类是对一类问题共同点的抽象,进行封装,实现一系列的功能。
一、
首先,类中要有数据成员与成员函数。并且数据成员一般都是是私有类型的,在主函数中一般无法直接访问,但可以通过在类中定义public成员函数,来对其在主函数中访问。这类函数称为访问器(getXX)和修改器(setXX)

class Rectangle {
public:
	double area();
	double perimeter();
//width 的访问器和修改器
	double getWidth(){return width;}
	void setWidth(double newWid)
		{ if(newWid > 0) width = newWid;	}
//height 的访问器和修改器
	double getHeight(){return height;}
	void setHeight(double newHei)
		{ if(newHei > 0) height = newHei; }
private:
	double width;
	double height;
}

或者可以在类中将需要访问私有数据的非成员函数声明为友元(friend),友元的定义非常广,可以是全局函数,可以是另一个类的成员函数或另一个类。

成员函数一般都是共有类型的,以便在主函数中进行访问。

二、
再有了数据成员后,要对其进行初始化,但有些数据成员无法直接赋值来初始化,如引用成员,const 数据成员,类类型的数据成员。就要用构造函数来初始化,称为构造函数初始化列表,形式如下:
成员1(初始值1)[,成员2(初始值2),…]
初始化列表位于构造函数的参数表之后,函数体之前
构造函数(参数表) : 初始化列表 { 函数体 }

class X {
int m, &r;
public:
X(int v):r(m) { m = v;}    //构造函数的名字与类名字相同,没有返回类型。
};

注意:
构造函数可以重构,并且构造函数至少要定义两个,其中一个无参数的。
在初始化列表中,每个成员只能出现一次
成员初始化的顺序与它们在类定义中出现的顺序一致
初始化列表中初值排列的顺序不影响实际的初始化顺序
如果可能的话,尽量避免用某些成员初始化其他成员,例如:

class X{
int a, b;			//成员声明顺序
public:
X(int val):a(val), b(a){} 	//先初始化a,再用a初始化b
};
//下面的形式更好一些: 用val 初始化,没有成员的依赖
X(int val) : a(val), b(val){}
//下面的形式可能会产生未定义的行为:试图用未定义的值b初始化a
X(int val) : b(val), a(b){} 	//编译器会警告

三、
在对象生存期间,构造函数或其他成员函数可能为对象分配某些资源例如为指针成员在动态存储区分配空间当对象生存期结束时,应返回或释放相关资源,这时就需要析构函数来负责在对象生存期结束时返回相关资源和自动释放资源。
析构函数的名字是类名字前加波浪线“~”,析构函数没有返回类型,也没有任何参数,析构函数不能重载,只能为一个类定义唯一一个析构函数。
注意
当对象生命期结束时,则会调用析构函数
析构函数绝大多数情况下都被自动地隐式调用,一般不要显式调用
例如:

#include<iostream>
using namespace std;
class X{
public:
X() {cout<<"constructor is called"<<endl;}
~X() {cout<<"destructor is called"<<endl;}
//...
};
int main()
{
  X obj;
  obj.~X();                      //显式调用析构函数
  }                        //离开作用域时,析构函数又被自动调用了一次!

四、
有的数据成员是不可以修改的,如学号,生日,那么则需要将数据成员定义为const数据成员,只读不写。同理,成员函数也可以定义为const成员函数

class X{
int m;
public:
X(int v = 0):m(v){}
void set(int v){ m = v;}
int get()const{ return m; }
};
……
const X b(5);			//const对象
b.get();				//OK
b.set(10);				//Error ,const对象不能调用非const成员函数。

***注意:***只有声明为const 的成员函数才可以被const 对象调用
const 对象不能调用非const 成员函数
非const 对象可以调用const 成员函数
const 成员函数中不能修改类的数据成员
const 成员函数中不能调用其他非const 成员函数
五、
static数据成员,属于整个类,不专属于某个对象,static数据成员被当作该类类型的全局变量,对非static数据成员,每个对象都有自己的副本,static数据成员对整个类类型只有一个,由这个类型的所有对象共享访问。
注意:
static数据成员属于类,不属于某个特定对象,因而不能在构造函数中初始化
static数据成员在类定义之外初始化,使用类名字限定
int Object::count = 0;
static成员只能定义一次。

访问静态数据成员:
在类的成员函数中可以直接访问static数据成员
在非成员函数中通过两种方式访问static数据成员
成员访问运算符“.”或“->”
像访问普通数据成员的语法一样,通过对象或指针来访问
类名限定的静态成员名
static成员只有一个副本,可以直接用类名字限定的静态成员名字访问
ClassName::StaticMemberName

class Object {
static int count; 		//静态数据成员
…
friend void func(Object& obj);
};
void func(Object& obj){
cout << obj.count; 		//成员访问语法
cout << Object::count; 	//类名限定访问
}

static成员函数,一般需要通过成员函数来访问数据成员
成员函数也可以访问static数据成员
普通成员函数必须通过类的对象或指针调用,而静态数据成员并不依赖对象存在
如果成员函数只访问静态数据成员,那么用哪个对象来调用这个成员函数都没有关系,因为调用的结果不会影响任何对象的非静态数据成员
可以将这样的成员函数声明为static成员函数
例如:

class Object {
static int count; 		//静态数据成员
public:
Object(){ count++; }
Object(const Object&) {count++; …}
~Object(){count--;}
static int getCount() 	 //静态成员函数
{ return count; }
} ;

感想:学习了类与对象,C++才开始正式的旅途,定义类的用途,主要实现对数据的增删查改,自定义数据类型,在对其封装数据,功能。具体化使用还要定义对象,即将一类问题普遍特性进行统一描写,再用于具体情况。对于类与对象,每增加一个成员函数都要对其验证,测试,否则出现将会很麻烦。以后在写代码的时候,要习惯用类的形式写,主函数只是调用类。加油,好好学习!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值