OOP的理念
主要的OOP特性:
- 抽象
- 封装和数据隐藏
- 多态(重载特性)
- 继承
- 代码的可重用性
从用户的角度来考虑如何使用对象,即接口。
类的定义
定义类的过程:
- 类声明:以数据成员的方式描述数据部分,以成员函数的方式描述公用接口。
- 类方法定义:描述如何实现对应的成员函数。
//声明,也即是原型
class stack
{
private: //私有数据,private可以省略
int a;
int b;
double c;
public: //公有接口
void short() { cout<<"inline function"<<endl;} //直接定义的函数,将作为内联函数
void func1() const; //const 函数
int func2();
stack(); //默认构造函数
stack(int m,int n,double q); //构造函数
~stack(); //析构函数
};
//定义过程,完成函数的定义
void stack::func1()const
{
...
}
stack::stack()
{
...
}
访问类型
类和结构的唯一区别在于,结构的默认访问类型是public,而类的默认访问类型为private。
成员函数
若某个成员为private,则只能通过公有的方法调用该方法进行使用。
定义位于类声明中的函数,将自动成为内联函数。(内联函数在每个使用它们的文件中都要对其进行定义)。
数据成员
每个对象的存储空间都只是它们的数据成员。也就是说,成员函数是一整个类的公有的部分。
类的构造函数和析构函数
在构造函数和析构函数中,可以使用对象中数据成员。
构造函数:
- 构造函数是没有声明类型的。
- 程序声明对象时,将自动调用构造函数。
- 无法使用对象来调用构造函数。
stack food=stack{1,2,3.4}; //#1构造函数
stack food{1,2,3.4}; //#2构造函数
stack food; //#3默认构造函数
默认构造函数:
当没有定义构造函数时,编译器将提供一个空的默认构造函数。
若定义了一个构造函数后,则必须再提供一个默认构造函数。
构造默认构造函数的方法:
- 给已有的构造函数的所有参数提供默认值
- 通过函数重载,再定义一个没有任何参数的构造函数
析构函数:
如果没有定义析构函数,编译器会默认提供一个析构函数。
可以通过析构函数观察得到,最先创建的对象,最后被清除。这是因为程序过程中,自动变量是存储在栈中的。
如果构造函数中使用了new语句,则在析构函数中一定要使用delete语句。
const成员函数
const成员函数主要用于避免对对象成员进行修改。
class stack
{
...
public :
void show()const;
};
void stack::show()const
{
...//const函数调用
}
const stack no_1; //表明对象no_1不可被修改,只能调用stack类中的const成员函数
this指针
this指针指向的是自身对象。*this是自身对象的别称。
每个成员函数(构造函数和析构函数)都有一个this指针。this指针指向调用对象。
应用实例:通过成员函数,来比较自身对象和另一个对象的数值大小。
stack & func(const stack & temp)const
{
...
if()
return *this;
else
return temp;
}
对象数组
stack buffer[4]; //调用默认构造函数
stack buffer[4]={stack(),stack(),stack(),stack()}; //调用构造函数进行初始化定义
stack one=stack();//默认构造函数
stack two=stack(a,b);//构造函数,拷贝初始化
stack three;//默认构造函数
stack four(a,b);//构造函数,直接初始化
对象初始化示例代码
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
class person
{
private:
static const int LIMIT=25;
string lname;
char fname[LIMIT];
public:
person()
{
lname="";
fname[0]='\0'; //注意不要把字符与字符串弄混淆 '' , ""
}
person(const string & ln,const char *fn="HEYyou");
void show()const;
void formalshow()const;
};
int main()
{
/********************三种初始化方法**********************************/
person one; //默认构造函数
person two=person("my"); //构造函数
person three=person("my","heart"); //构造函数
/******************************************************/
two.show();
cout<<endl;
two.formalshow();
}
person::person(const string & ln,const char *fn) //定义处不写默认值
{
lname=ln;
strcpy(fname,fn);
}
void person::show()const
{
cout<<"first name:"<<fname<<endl;
cout<<"last name:"<<lname<<endl;
}
void person::formalshow()const
{
cout<<"first name:"<<this->fname;
cout<<"last name:"<<this->lname;
}
类作用域
类中声明的名称:变量或者成员函数的名称,作用域都是整个类。
在类声明之外,定义成员函数时,必须使用作用域解析符,如stack::。
在类中声明一个常量有两种方式:
- 声明一个枚举变量。enum {years=12};
- 使用static关键字。static const int years=12;//只存储一个years变量,所有stack类对象共享该变量。
抽象数据类型(ADT)
可以用于设计队列,堆栈,等抽象的数据类型。
//堆栈基础实现 :只能存储特殊的数据类型
#include<iostream>
using namespace std;
struct customer
{
char fullname[35];
double payment;
};
class stack
{
private :
customer buffer[3];
int top;
public:
stack()
{
top=0;
}
customer pop();
void push(const customer & temp);
bool is_full();
bool is_empty();
};
int main()
{
stack one;
customer temp_1;
while(!one.is_full())
{
cout<<"input a customer"<<endl;
cout<<"name: ";
cin>>temp_1.fullname;
cout<<endl<<"payment: ";
cin>>temp_1.payment;
one.push(temp_1);
}
while (!one.is_empty())
{
temp_1=one.pop();
cout<<"name: "<<temp_1.fullname;
cout<<"\n paynament: "<<temp_1.payment<<endl;
}
}
customer stack::pop()
{
customer temp;
temp=buffer[top];
top--;
return temp;
}
void stack::push(const customer &temp)
{
buffer[top+1]=temp;
top++;
}
bool stack::is_full()
{
return (top==2);
}
bool stack::is_empty()
{
return (top==0);
}