文章目录
面向对象的程序设计基础
面向对象的程序设计方法:
· 将某类客观事务共同特点(属性归纳出来),形成一个数据结构;
· 将这类事务所能进行的行为也归纳出来,形成一个个函数。
面向对象的程序设计的四个基本特点:抽象、封装、继承、多态。
类的成员函数和类的定义分开写
class CRectangle
{
public:
int w,h;
int Area();
int Perimeter();
void Init(int w_, int h_);
}
int CRectangle::Area() {
return w*h;
}
int CRectangle::Perimeter() {
return 2*(w+h);
}
void CRectangle::Init(int w_, int h_){
w=w_; h=h_;
}
CRectangle::说明后面的函数是CRectangle类的成员函数。
类成员的可访问范围
-private:私有成员,只能在成员函数内访问
-public:公有成员,任何地方
-protected:保护成员
成员函数的重载及缺省参数
成员函数也可以重载,可以带缺省参数
构造函数
名字与类名相同,可以有参数,不能有返回值。
作用是对对象进行初始化,如给成员变量赋初值。
如给定义类时没写构造函数,则编译器生成一个默认的无参数的构造函数。
对象生成时构造函数自动被调用。对象一旦生成,就再也不能在其上执行构造函数。
可以有多个构造函数,参数个数或类型不同。
class Complex{
private:
double real, imag;
public:
Complex(double r, double i);
Complex(double r);
Complex(Complex c1, Complex c2);
}
复制构造函数
· 只有一个参数,即对同类对象的引用。
· 形如X::X(X&)或X::X(const X &),二者选一,后者能以常量对象作为参数。
· 若没有定义复制构造函数,那么编译器生成默认。
class Complex{
private:
double real, imag;
};
Complex c1; // 调用缺省无参数构造函数
Complex c2(c1); // 调用缺省的复制构造函数,将c2初始化成和c1一样
类型转换构造函数
实现类型的自动转换。
class Complex{
public:
double real, imag;
Complex(int i){
cout<<"IntConstructor called"<<endl;
real=i;imag=0;
}
Complex(double r, double i) { real=r;imag=i; }
};
int main()
{
Complex c1(7,8);
Complex c2=12;
c1=9;
}
析构函数
析构函数在对象作为函数返回值返回后被调用
构造函数和析构函数的调用时机
class Demo{
int id;
public:
Demo(int i){
id=i;
cout<<"id="<<id<<" constructed"<<endl;
}
~Demo() {
cout<<"id="<<id<<" destructed"<<endl;
}
};
面向对象的程序设计提高
this指针
非静态成员函数中可以直接使用this来代表指向该函数作用的对象的指针。
class Complex{
public:
double real,imag;
void Print() { cout<<real<<","<<imag; }
Complex(double r, double i): real(r), imag(i) {}
Complex AddOne() {
this->real++; // 等价于real++
this->Print(); // 等价于Print
return *this;
}
}
int main()
{
Complex c1(1,1),c2(2.0);
c2 = c1.AddOne();
return 0;
}
class A
{
int i;
public:
void Hello() { cout<<"hello"<<endl; }
};// -> void Hello(A *this) { cout<<"hello"<<endl; }
int main()
{
A *p = NULL;
p->Hello();
}// 输出hello
this指针和静态成员函数
静态成员函数中不能使用this指针!
因为静态成员函数并不具体作用与某个对象。
因此,静态成员函数的真实的参数的个数,就是程序中写出的参数个数。
静态成员变量
静态成员:在说明前命加了static关键字的成员。
普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享。
普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。
静态成员不需要通过对象就能访问。
sizeof 运算符不会计算静态成员变量。
class Myclass{
int n;
static int s;
};
则sizeof(CMyclass)等于4。
如何访问静态成员:
1)类名::成员名
CRectangle::PrintTotal();
2)对象名.成员名
CRectangle r;
r.PrintTotal();
3)指针->成员名
CRectangle *p = &r;
p->PrintTotal();
4)引用.成员名
CRectangle &ref=r;
int n = ref.nTotalNumber;
静态成员变量本质上是全局变量,哪怕一个对象也不存在,类的静态成员变量也存在。
静态成员函数本质上是全局函数。
设置静态成员这种机制的目的是将和某些紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解。
例:对于矩形类,需要随时指导矩形总数和总面积的图形处理程序。
可以用全局变量来记录总述和总面积( 用静态成员将这两个变量封装进类中)。
class CRectangle
{
private:
int w,h;
static int nTotalArea;
static int nTotalNumber;
public:
CRectangle(int w_, int h_);
~CRectangle();
static void PrintTotal();
};
CRectangle::CRectangle(int w_, int h_)
{
w=w_;
h=h_;
nTotalNumber++;
nTotalArea+=w*h;
}
CRectangle::~CRectangle()
{
nTotalNumber--;
nTotalArea-=w*h;
}
void CRectangle::PrintTotal()
{
cout<<nTotalNumber<<","<<nTotalArea<<endl;
}
在使用CRectangle类时,有时会调用复制构造函数生成临时的隐藏的CRectangle对象:
调用一个以CRectangle类对象作为参数的函数时。
调用一个以CRectangle类对象作为返回值的函数时。
临时对象在消亡时会调用析构函数,减少nTotalNumber和nTotalArea的值,也就是平白无故的减少了。
解决办法:为CRectangle类写一个复制构造函数。
成员对象和封闭类
封闭类:有成员对象的类。
未完待续…