C++类&对象
C++类&对象
C++在C语言的基础上增加了面向对象编程,C++支持面向对象程序设计。类是C++的核心特性,通常被称为用户定义的类型。
类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。
- C++类定义
定义一个类,本质上是定义一个数据类型的模板。实际上并没有定义任何数据。也就是说,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
类定义是以关键字class开头,后跟类的名称。类的主体是包含在一对花括号中,类定义后必须跟着一个分号或者一个声明列表。例如石永红关键字class定义Box数据类型,如下所示:
class Box
{
public:
double length;
double breadth;
double height;
};
关键字public确定了类成员的访问属性。在类对象作用域内,公共成员在类的外部是可访问的。也可以指定类的成员为private或protected。
- 定义C++对象
类提供了对象的蓝图或模板,基本上对象是根据类来创建的,声明类的对象,就像声明基本类型的变量一样。下面的语句声明了类Box的两个对象:
Box Box1;//声明
Box Box2;
对象Box1和Box2都有各自的数据成员。
- 访问数据成员
类的对象的公共数据成员可以使用直接成员访问运算符(.)来访问。为了理解概念,尝试以下实例:
#include<iostream>
using namespace std;
class Box{
public:
double length;
double breadth;
double height;
};
int main(){
Box Box1;
Box Box2;
double volume = 0.0;
double volume2 = 0.0;
Box1.height = 5.0;
Box1.length = 6.0;
Box1.height = 7.0;
Box2.height = 10.0;
Box2.length = 12.9;
Box2.height = 13.9;
volume = Box1.height*Box1.length*Box1.height;
cout<<" volume of Box1:"<<volume<<endl;
volume2 = Box2.height*Box2.length*Box2.height;
cout<<"Volume of Box2:"<<volume2<<endl;
return 0;
}
结果显示:

注意:私有成员和受保护的成员不能使用直接访问运算符(.)来直接访问。
类成员函数
类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,可以操作类的任意对象,可以访问对象中的所有成员。
现在要使用成员函数访问类的成员,而不是直接访问这些类的成员。
class Box{
public:
double length;
double breadth;
double height;
double getVolume(void);//返回体积
};
成员函数可以定义在类定义内部,或者单独使用范围解析运算符::来定义。在类定义中定义的成员函数把函数声明为内联的,即使没有使用inline标识符。所以可以按照如下方式定义volume()函数:
class Box{
public:
double length;
double breadth;
double height;
double getVolume(void){
return length*breadth*height;
}
};
也可以在类的外部使用范围解析运算符::定义该函数,如下所示:
double Box::getVolume(void){
return length*breadth*height;
}
需要强调一点,在::运算符之前必须使用类名。调用成员函数是在对象上使用点运算符(.),这样就能操作与该对象相关的数据,如下所示:
Box myBox;//创建一个对象
myBox.getVolume();//调用该对象的成员函数
实例:
#include<iostream>
using namespace std;
class Box{
public:
double length;
double breadth;
double height;
double getVolume(void);//成员函数声明
void setLength(double len);
void setBreadth(double bre);
void setHeight(double hei);
};
//成员函数定义
double Box::getVolume(void){
return length*breadth*height;
}
void Box::setLength(double len){
length = len;
}
void Box::setBreadth(double bre)
{
breadth = bre;
}
void Box::setHeight(double hei){
height = hei;
}
int main(){
Box Box1;
Box Box2;
double volume = 0.0;
double volume2 = 0.0;
//box1详述
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
//box2详述
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(14.0);
volume = Box1.getVolume();
cout<<" volume of Box1:"<<volume<<endl;
volume2 = Box2.getVolume();
cout<<"Volume of Box2:"<<volume2<<endl;
return 0;
}
结果显示:

C++类访问修饰符
数据隐藏是面向对象编程的一个重要特点,防止函数直接访问类类型的内部成员。类成员的访问限制是通过在类主体内部对各个区域标记public、private、protected来指定的。关键字public、private、protected称为访问说明符。一个类可以有多个public、protected或private标记区域。每个标记区域在下一个标记区域开始之前或者在遇到类主体结束右括号之前都是有效的。成员和类的默认访问修饰符是private。
class Base{
public:
protected;
private;
};
- 公有成员(public)
公有成员在程序中类的外部是可访问的,可以不使用任何成员函数来设置和获取公有变量的值,如下所示:
#include<iostream>
using namespace std;
class Line{
public:
double length;
void setLength(double len);
double getLength(void);
};
//成员函数
double Line::getLength(void){
return length;
}
void Line::setLength(double len){
length = len;
}
int main(){
Line line;
line.setLength(6.0);//设置长度
cout<<"Length of line:"<<line.getLength()<<endl;
//不使用成员函数设置长度
line.length = 10.0;//因为length是公有的
cout<<"Length of line:"<<line.length<<endl;
return 0;
}
结果显示:

- 私有(private)成员
私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。默认情况下,类的所有成员都是私有的,例如在下面的类中,width是一个私有成员,这意味着如果没有使用任何访问修饰符,类的成员将被假定为私有成员。
class Box
{
double width;
public:
double length;
void setWidth(double wid);
double getWidth(void);
};
实际操作中,一般会在私有区域定义数据,在公有区域定义相关函数,以便在类的外部也可以调用这些函数,实例:
#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;//不使用成员函数设置长度
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;
}
结果显示:

- 保护成员(protected)
保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的。从父类Box派生一个子类smallBox。
实例:
#include<iostream>
using namespace std;
class Box{
protected:
double width;
};
class SmallBox:Box//SmallBox是派生类
{
public:
void setSmallWidth (double wid);
double getSmallWidth(void);
};
//子类的成员函数
double SmallBox::getSmallWidth(void){
return width;
};
void SmallBox::setSmallWidth(double wid){
width = wid;
}
int main(){
SmallBox box;
box.setSmallWidth(5.0);
cout<<"Width of box:"<<box.getSmallWidth()<<endl;
return 0;
}
结果显示:

C++构造函数和析构函数
- 类的构造函数
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回Void。构造函数可用于为某些成员变量设置初始值。
实例:
#include<iostream>
using namespace std;
class Line{
public:
void setLength(double len);
double getLength(void);
Line();//这是构造函数
private:
double length;
};
//成员函数定义,包括构造函数
Line::Line(void){
cout<<"Object is being created"<<endl;
}
void Line::setLength(double len){
length = len;
}
double Line::getLength(void){
return length;
}
//程序的主函数
int main(){
Line line;
line.setLength(6.0);
cout<<"Length of line:"<<line.getLength()<<endl;
return 0;
}
结果显示:

- 带参数的构造函数
默认的构造函数没有任何参数,但如果需要,构造函数也可以带参数。这样在创建对象时就会给对象赋初始值,如下面的例子所示:
#include<iostream>
using namespace std;
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;
}
void Line::setLength(double len){
length = len;
}
double Line::getLength(void){
return length;
}
int main(){
Line line(10.0);
cout<<"Length of line:"<<line.getLength()<<endl;
//设置长度
line.setLength(6.0);
cout<<"Length of line:"<<line.getLength()<<endl;
return 0;
}
结果显示:

- 使用初始化列表来初始化字段
使用初始化列表来初始化字段:
Line::Line(double len):
Length(len){
cout<<"Object is being created, length = "<<len<<endl;
}
等同于
Line::Line(double len){
cout<<"Object is being created, length = "<<len<<endl;
length = len;
}
假设一个类C,具有多个字段X、Y、Z等需要初始化,只需要在不同的字段使用逗号进行分隔,如下所示:
C::C(double a, double b, double c):X(a),Y(b),Z(c){
...
}
- 类的析构函数
类的析构函数是类的一种特殊的成员函数,它会在,每次删除所创建的对象时执行。析构函数的名称与类的名称是完全相同的,只是在前面加个波浪号~作为前缀,它不会返回任何值,也不能带任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
实例:
#include<iostream>
using namespace std;
class Line{
public:
void setLength(double len);
double getLength(void);
Line();//构造函数声明
~Line();//析构函数声明
private:
double length;
};
Line::Line(void){
cout<<"Object is being created"<<endl;
}
Line::~Line(void){
cout<<"Object is being created"<<endl;
}
void Line::setLength(double len){
length = len;
}
double Line::getLength(void){
return length;
}
int main(){
Line line;
line.setLength(6.0);
cout<<"Length of line:"<<line.getLength()<<endl;
return 0;
}
结果显示:

C++拷贝构造函数
首先对于普通类型的对象来说,它们之间的复制是很简单的,例如:
int a = 100;
int b = a;
而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。
实例:
#include<iostream>
using namespace std;
class CExample{
private:
int a;
public:
//构造函数
CExample(int b){
a = b;
}
//一般函数
void Show(){
cout<<a<<endl;
}
};
int main(){
CExample A(100);
CExample B = A;//注意这里的对象初始化要调用拷贝构造函数,而非赋值
B.Show();
return 0;
}
结果显示:

从以上代码可以看出,系统为对象B分配了内存并完成了与对象A的复制过程,就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:
- 通过使用另一个同类型的对象来初始化新创建的对象。
- 复制对象把它作为参数传递给函数。
- 复制对象,并从函数返回这个对象。
如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:
classname (const classname &obj){
//构造函数的主体
}
在这里,obj是一个对象引用,该对象是用于初始化另一个对象的。
#include<iostream>
using namespace std;
class Line{
public:
int getLength(void);
Line(int len);//简单的构造函数
Line(const Line &obj);//拷贝构造函数
~Line();//析构函数
private:
int *ptr;
};
//成员函数定义,包括构造函数
Line::Line(int len){
cout<<"Normal constructor allocating ptr"<<endl;
//为指针分配内存
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj){
cout<<"Copy constructor allocating ptr."<<endl;
ptr = new int;
*ptr = *obj.ptr;//复制该值
}
Line::~Line(void){
cout<<"Freeing memory!"<<endl;
delete ptr;
}
int Line::getLength(void){
return *ptr;
}
void display(Line obj){
cout<<"Length of line:"<<obj.getLength()<<endl;
}
int main(){
Line line(10);
display(line);
return 0;
}
结果显示:

下面实例对上面的实例稍作修改,通过使用已有的同类型的对象来初始化新创建的对象:
#include<iostream>
using namespace std;
class Line{
public:
int getLength(void);
Line(int len);//简单构造函数
Line(const Line &obj);//拷贝构造函数
~Line();//析构函数
private:
int *ptr;
};
//成员函数定义,包括构造函数
Line::Line(int len){
cout<<"Normal constructor allovating ptr"<<endl;
//为指针分配内存
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj){
cout<<"copy contsructor allocating ptr."<<endl;
ptr = new int;
*ptr = *obj.ptr;//拷贝值
}
Line::~Line(void){
cout<<"Freeing memory!"<<endl;
delete ptr;
}
int Line::getLength(void){
return *ptr;
}
void display(Line obj){
cout<<"Length of line:"<<obj.getLength()<<endl;
}
int main(){
Line line1(10);
Line line2 = line1;//调用拷贝构造函数
display(line1);
display(line2);
return 0;
}
结果显示:
C++友元函数
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。友元可以是一个函数,该函数被称为
友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend,如下所示:
class Box
{
double width;
public:
double length;
friend void printWidth(Box box);
void setWidth(double wid);
};
声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中放置如下声明:
friend class ClassTwo;
实例:
#include <iostream>
using namespace std;
class Box{
double width;
public:
friend void printWidth(Box box);
void setWidth(double wid);
};
//成员函数定义
void Box::setWidth(double wid){
width = wid;
}
//注意printWidth()不是任何类的成员函数
void printWidth(Box box){
//因为printWidth()是Box的友元,它可以直接访问该类的任何成员
cout<<"Width of box:"<<box.width<<endl;
}
int main(){
Box box;
//使用成员函数设置宽度
box.setWidth(10.0);
printWidth(box);//使用友元函数输出宽度
return 0;
}
结果显示:

C++内联函数
在C++中国我们通常定义以下函数来求两个整数的最大值:
int max(int a, int b){
return a > b? a: b;
}
但是这样写存在一个潜在的缺点,调用函数比求解等价表达式要慢得多。在大多数机器上,调用函数都要做很多工作:调用前要先保存寄存器,并在返回时恢复,复制实参,程序还必须转向一个新位置执行。在C++中可以使用内联函数
其目的是为了提高函数的执行效率,通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。
对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数。
如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字inline,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略inline限定符。在类定义中的定义的函数都是内联函数,即使没有使用inline说明符。
实例:
``
include
using namespace std;
inline int Max(int x, int y){
return (x>y)?x:y ;
}
int main(){
cout<<"Max(20, 10):"<<Max(20, 10)<<endl;
cout<<"Max(0, 200):"<<Max(0,200)<<endl;
cout<<"Max(100, 1010):"<<max(100, 1010)<<endl;
return 0;
}
结果显示:

#### C++ this指针
在C++中,每一个对象都能通过this指针来访问自己的地址。this指针是所有成员函数的隐含参数。因此在成员函数内部,它可以用来指向调用对象。
友元函数没有this指针,因为友元不是类的成员。只有成员函数才有this指针。
实例:
include
using namespace std;
class Box
{
public:
//构造函数
Box(double l=2.0, double b=2.0,double h=2.0){
cout<<"Constructor called."<<endl;
length = l;
breadth = b;
height = h;
}
double Volume(){
return length * breadth * height;
}
int compare(Box box){
return this->Volume()>box.Volume();
}
private:
double length;
double breadth;
double height;
};
int main(){
Box Box1(3.3, 1.2, 1.5);
Box Box2(8.5, 6.0, 2.0);
if (Box1.compare(Box2)){
cout<<"Box2 is smaller than Box1"<< endl;
}
else{
cout<<"Box2 is equal to or larger than Box1"<<endl;
}
return 0;
}
结果输出:

#### C++中指向类的指针
一个指向C++类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符->,就像访问指向结构的指针一样。与所有的指针一样,必须在使用指针之前,对指针进行初始化。
实例:
include
using namespace std;
class Box{
public:
//构造函数
Box(double l =2.0, double b = 2.0, double h = 2.0){
cout<<"constructor called."<<endl;
length = l;
breadth = b;
height = h;
}
double Volume(){
return length*breadth*height;
}
private:
double length;
double breadth;
double height;
};
int main(){
Box Box1(3.3, 1.2, 1.5);
Box Box2(8.5, 6.0, 2.0);
Box *ptrBox;
ptrBox = &Box1;
cout<<"Volume of Box1:"<
ptrBox = &Box2;
cout<<"Volume of Box2:"<
return 0;
}
结果显示:

#### C++类的静态成员
可以使用static关键字来把类成员定义为静态的。当声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。
静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。不能把静态成员放置在类的定义中,但是可以在类的外部通过使用范围解析运算符::来重新声明
静态变量从而对它进行初始化,如下面的实例所示:

浙公网安备 33010602011771号