一、什么是类
类是面向对象程序设计的核心。实际上是新的数据类型,是实现抽象类型的工具。
类是对某一类对象的抽象,对象是某一类的实例。
1、类的一般格式:
class<类名>
{
private:
<私有数据和函数>
public:
<公有数据和函数>
protected:
<保护型数据和函数>
};//此处(类体最后一个花括号)一定要有分号
<各个成员函数的实现>
2、类的定义一般分为声明部分和实现部分。
类声明
class Human
{
public:
//...data
private:
//...data
}
class是个关键字,用其来声明类
3、类范围
类的私有成员具有类范围性质,类的私有成员仅能由类的成员函数访问。
class C{
public:
void m(); //public scope
private:
char d; //class scope (private scope)
};
这个例子中的类声明赋予数据成员d类范围性质(因为d是私有的)。
在C++中,用关键字class来声明的类,其类成员在默认情况下具有类范围性质,在这种情况下,如果没有为类成员指定任何访问限制符(public、private或protected),这个成员将作为私有成员处理。
注:关键字class和struct区别
使用class关键字或struct关键字都可以创建类。如果使用class关键字,类成员在默认状态下是私有的;而使用struct关键字,类成员在默认状态下是公有的。
二、类成员函数的定义
类成员函数定义有两种途径:
成员函数的声明在类声明之中进行,但在类声明之外定义。
成员函数的定义也可在类声明之中进行,这种定义方式为inline,C++关键字inline专门用来表示内联。
内联定义方式同时提供了成员函数的声明和定义。
class Person
{
public:
void setAge( unsigned n );
unsigned getAge() const;
private:
unsigned age;
};
void person::setAge( unsigned n)
{
age = n;
}
usigned Person::getAge() const
{
return age;
}
本例在类声明之中声明了Person类的各种成员函数,然后在类的声明之外定义这些函数,在定义成员函数时使用了域解析“::” 。
class Person
{
public:
void setAge( unsigned n ){ age = n;}
unsigned getAge() const { return age; };
private:
unsigned age;
};
这个例子中在类声明中定义了Person类的各种成员函数,所以这些函数都是inline类型的。内联函数通知编译器用成员函数的函数体替换掉所有对该函数进行声明调用的代码,这样在替换后的代码中不再出现对这个函数进行调用的代码。
class Person
{
public:
inline void setAge( unsigned n );
inline unsigned getAge() const;
private:
unsigned age;
};
void person::setAge( unsigned n)
{
age = n;
}
usigned Person::getAge() const
{
return age;
}
而通过在进行成员函数声明的时候使用inline关键字,可将原本定义在类声明之外的成员函数强制变成内联函数。
三、.对象的定义
有三种定义:声明之后定义、声明之时定义和一次性定义。但由于“类”比任何数据类型都复杂为了提高程序可读性,最好在对象的声明之后定义。
定义格式:
<类名>.<对象名>
类名是用户已定义过的类的标识符,对象名可以有一个和多个,多个时要用逗号分隔。被定义的对象可以是一个普通对象,一个数组和一个指针对象。
如:CMeter myMeter,*Meter,Meter[2];
一个对象的成员就是该对象的类所定义的数据成员和成员函数。
访问方法:在成员前面加上对象名和成员运算符“.”,其表示方法如下:
<对象名>.<成员变量>
<对象名>.<成员函数>(<参数>)
如:myMeter.m_nprrcent ,myMeter.SetPos(2)
需要说明:一个类对象只能访问该类的公有型成员,而对于私有型成员则不能访问。
若对象是一个指针,则对象成员访问形式如下:
<对象指针名>-><成员变量>
<对象指针名>.<成员函数>(<参数>)
需要说明:下面两种表示是等价的
<对象指针名>-><成员变量>
(*<对象指针名>).<成员变量>
四、通过引用传递和返回对象
和其他类型的变量一样,对象既可以采用传值方式传递给函数,也可以采用引用方式作为函数的返回值。除非迫不得已,一般来说应该采用引用方式进行对象的传递和返回,而不要采用传值的方式来进行。这是因为通过传值方式来传递和返回对象时会降低效率并将面临对象间的拷贝操作,从而使数据增大,浪费内存。而采用引用方式,则完全可以避免上述弊病。
五、构造函数和析构函数
a. 构造函数:
C++中的类需要定义与类名相同的特殊成员函数时,这种与类名相同的成员函数叫做构造函数;
构造函数可以在定义的时候有参数;
构造函数没有任何返回类型。
构造函数的调用: 一般情况下,C++编译器会自动的调用构造函数。特殊情况下,需要手工的调用构造函数。
class Test
{
public:
//构造函数
Test()
{
}
}
b. 析构函数:
C++中的类可以定义一个特殊的成员函数清理对象,这个特殊的函数是析构函数;
析构函数没有参数和没有任何返回类型;
析构函数在对象销毁的时候自动调用;
析构函数调用机制: C++编译器自动调用。
class Test
{
~Test()
{
}
}
六、const类型参数对象引用
通常,如果一个对象通过引用方式传到函数f中,而函数f又不会通过修改对象的数据成员的值改变该对象的状态,那么,最好将f的参数标记为const,可以预防对象参数的误写,同时有些编译器还可以对这种情况进行一些优化。
class C {
public:
void setName( const string& n) {name = n; }
private:
string name;
};
函数setname的string类型参数n标记为const,表明setName不会改变n,只将n赋值给数据成员name。
七、const成员函数
class C{
public:
void set( int n ) { num = n;}
int get() const {return num;}
private:
int num;
};
这个例子中,由于get成员函数不需要改变类C的任何数据成员,因此将get成员函数标记为const,注意,const关键字出现在参数列表与其函数体之间。
由于get成员函数不更改任何数据成员,因此称这种类型的函数为只读函数。
一个const成员函数仅能调用其他const成员函数,因为const成员函数不允许直接或间接地改变对象的状态,而调用非const成员函数可能会间接地改变对象的状态。
class C{
public:
void set( const string& n) {name = n; }
const string& get() const{ return name; }
private:
string name;
};
在成员函数set中,因为set不改变string类型参数n,n被标记为const。成员函数get返回数据成员name的一个const型引用,此处的const表明谁也不能通过这个引用来修改数据成员name的值。成员函数get本身被标记为const,因为get不会改变类C唯一的数据成员name的值。