封装 Encapsulation
可以将多个类型打包成一体,形成新的类型。
C语言的封装风格 数据放到一起打包 struct
然后把数据以引用或指针的方式传给行为
#include <iostream>
using namespace std;
struct Man
{
string name;
int age;
char sex;
float high;
float salary;
};
struct Date
{
int year;
int month;
int day;
};
//封装成函数
void init(Date d)
{
cin>>d.year;
cin>>d.month;
cin>>d.day;
}
void print(Date & d)
{
cout<<"year: "<<d.year<<" month: "<<d.month<<" day: "<<d.day<<endl;
}
bool isLeapYear(Date & d)
{
if(d.year % 4 == 0 && d.year % 100 != 0 || d.year % 400 == 0)
return true;
else
return false;
}
int main()
{
Date d; //定义变量,开辟空间
init(d);
print(d);
if(isLeapYear(d))
cout<<d.year<<" is leap year"<<endl;
else:
cout<<d.year<<" is not leap year"<<endl;
return 0;
}
C++认为C语言封装不彻底
数据和行为分类,没有权限控制。对内数据开放,逻辑抽象。对外提供接口。
声明和实现要分开,使用类
#include <iostream>
using namespace std;
//权限控制 private protected public
//数据和行为在一起
//对内开放数据,逻辑抽象
//对外提供接口
class Date
{
public:
void init()
{
cin>>year;
cin>>month;
cin>>day;
}
int getYear()
{
cout<<year<<endl;
}
void print()
{
cout<<"year:"<<"month:"<<"day:"<<endl;
cout<<year<<":"<<month<<":"<<day<<endl;
}
protected:
int year;
int month;
int day;
};
int main()
{
Date d;
// d.year = 3000;
d.print();
return 0;
}
#include <iostream>
using namespace std;
class Date
{
public:
void init(); // 类函数成员
void print();
int getYear();
bool isLeapYear();
private:
int year; //数据成员
int month;
int day;
}
void init() //全局
{
}
class BB
{
public:
void init();
}
void Date::init()
{
cin>>year;
cin>>month;
cin>>day;
}
void BB::init()
{
}
int main()
{
return 0;
}
类名其实也是一种变相的命名空间
举例:栈
stack.h
#ifndef STACK_H
#define STACK_H
class Stack
{
public:
void init();
bool isEmpty();
bool isFull();
char pop();
void push(char c);
private:
char space[1024];
int top;
}
#endif // STACK_H
stack.cpp
#include "stack.h"
#include <iostream>
#include <stdlib.h>
#include <string.h>
void Stack::init()
{
top = 0;
memset(space, 0, 1024);
}
bool Stack::isEmpty()
{
return top == 0;
}
bool Stack::isFull()
{
return top == 1024;
}
char Stack::pop()
{
return space[--top];
}
void Stack::push(char c)
{
space[top++] = c;
}
main.cpp
#include <iostream>
#include "stack.h"
using namespace std;
int main()
{
Stack st;
st.init();
for(char v = 'a'; !st.isFull() && v != 'z'; v++)
{
st.push(v);
}
while(!st.isEmpty())
cout<<st.pop()<<endl;
return 0;
}
写在main.cpp一个文件中的
#include <iostream>
#include <stdlib.h>
using namespace std;
class Stack
{
public:
void init();
bool isEmpty();
bool isFull();
char pop();
void push(char c);
private:
char space[1024];
int top;
};
void init(Stack & s)
{
s.top = 0;
memset(s.space, 0, 1024);
}
bool isEmpty(Stack & s)
{
return s.top == 0;
}
bool isFull(Stack & s)
{
return s.top == 1024;
}
char pop(Stack & s)
{
return s.space[--s.top];
}
char push(Stack & s, char c)
{
s.space[s.top++] = c;
}
int main()
{
Stack st;
init(st);
if(!isFull())
push(st, 'a');
while(!isEmpty(st))
cout<<pop(st)<<endl;
return 0;
}
构造器、析构器
constructor 构造器
1、与类名相同,无返回值,被系统生成对象时自动调用,用于初始化
2、可以有参数,构造器的重载,默认参数。重载和默认不能同时存在
3、若未提供任何构造器,系统默认生成一个无参空构造器。若提供则不再生成默认构造器
#ifndef STACK_H
#define STACK_H
class Stack
{
public:
Stack() //无参构造
{
top = 0;
space = new char[1000];
}
Stack(int size) //有参构造
{
top = 0;
space = new char[size];
_size = size;
}
void init();
bool isEmpty();
bool isFull();
char pop();
void push(char c);
~Stack()
{
cout<<""<<endl;
}
private:
char space[1024];
int top;
int size;
}
#endif // STACK_H
destructor 析构器
1、~ 与类名相同,无参,无返回,对象消失时自动被调用。
2、用于对象销毁时的内存处理工作。
3、若未提供,系统置信生成一个空析构器。
举例:构建钟表
#include <iostream>
#include <time.h>
#include <iomanip>
#include <unistd.h>
using namespace std;
//初始化的数据来自系统,以后的逻辑运算及显示自实现
class Clock
{
public:
Clock()
{
time_t t = time(NULL);
struct tm ti = *localtime(&t); //获得系统时间 struct tm *__cdecl localtime(const time_t * _Time)
hour = ti.hour;
min = ti.min;
sec = ti.sec;
}
void run()
{
while(1)
{
show(); // 完成显示
tick(); // 数据更新
}
}
private:
void show()
{
system("clear");
cout<<setw(2)<<setfill('0')<<hour<<":";
cout<<setw(2)<<setfill('0')<<min<<":";
cout<<setw(2)<<setfill('0')<<sec;
}
void tick()
{
sleep(1);
if(++sec == 60)
{
sec = 0;
if(++min == 60)
{
min = 0;
if(hour == 24)
{
hour = 0;
}
}
}
}
int hour;
int min;
int sec;
};
int main()
{
Clock c;
c.run();
return 0;
}
Const修饰符
1、const修饰数据成员、成员函数、类对象
2、修饰数据成员时,初始化位置只能在参数列表中
被const修饰的数据成员不能被修改
3、修饰成员函数
位置:函数声明之后,函数实现体之前
意义:const函数承诺不会修改数据成员
能访问const 和非const数据成员,但不能修改非const数据成员
只能访问const成员函数。
构成重载
const对象只能调用const成员函数。
非const成员对象,优先调用非const成员函数,若无,则可调用const成员函数。
4、修饰类对象
const修饰函数,是从函数的层面,不修改数据。
const修饰对象,是从对象的层面,不修改数据,只能调用const成员函数。
#include <iostream>
using namespace std;
class A
{
public:
A(int v)
:val(v)
{
}
void dis()
{
cout<<val<<endl;
}
void dis() const
{
cout<<"void dis() const"<<endl;
}
private:
const int val;
};
int main()
{
A a;
a.dis();
return 0;
}
Static静态
全局变量 外延性 static 作用域:仅限于本文件 生命周期、存储位置
局部变量 auto
static 在类内部的表现,用来实现族类对象间的数据共享
在生成对象的时候,普通数据成员才有空间。而static成员在类声明的时候就已经开辟了空间(在data rw段)。
类本质也是一个命名空间
1、初始化 类内定义,类外初始化。type 类名::变量名 = 初始值
2、static 数据成员,既属于类,也属于对象,但终归属于类
3、static 修饰的成员函数,因为属于类,没有this指针,不能访问非static数据成员及成员函数
#include <iostream>
using namespace std;
//static 修饰成员函数,作用只用于管理static成员
class School
{
public:
string & getTower()
{
return power;
}
static string & getLib()
{
return lib;
}
private:
string power;
string lake;
static string lib;
};
string School::lib = "aaaaa"; // 初始化静态数据成员,否则报错——C++无法解析的外部符号
int main()
{
School::getLib() = "aa";
School::getLib() += "bb";
School cz, bn, blue;
cz.getTower() = "aaa";
bn,getTower() = "bbb";
blue.getTower() = "ccc";
cz.getLib() += "ddd";
bn.getLib() += "eee";
blue.getLib() += "fff";
cout<<cz.getLib()<<endl;
cout<<bn.getLib()<<endl;
cout<<School::getLib()<<endl;
return 0;
}
#include <iostream>
using namespace std;
class CCSprite
{
public:
CCSprite(int d)
{
data = d;
if(head == NULL)
{
this->next = NULL;
head = this;
}
else
{
this->next = head->next;
head = this;
}
}
static void traverseCCSprite()
{
CCSprite * ph = head;
while(ph != NULL)
{
cout<<ph->data<<endl;
ph = ph->next;
}
}
private:
int data;
CCSprite * next;
static CCSprite * head;
};
CCSprite * CCSprite::head = NULL; //在外边初始化
int main()
{
CCSprite a(1), b(2), c(3);
for(int i = 100; i < 100; i++)
new CCSprite(i);
CCSprite::traverseCCSprite();
return 0;
}
指向类成员
#include <iostream>
#include "string.h"
using namespace std;
class Stu
{
Stu(string sn, int ia):
name(sn), age(ia){}
void print()
{
cout<<name<<"--"<<age<<endl;
}
public:
string name;
int age;
};
int main()
{
Stu s1("aaa", 39);
Stu s2("bbb", 79);
string Stu::* pn = &Stu::name;
cout<<s1.name<<s2.name<<endl;
cout<<s1.*pn<<s2.*pn<<endl; // .*
return 0;
}
#include <iostream>
using namespace std;
class Widget
{
public:
Widget()
{
pa[0] = &f;
pa[1] = &g;
pa[2] = &i;
pa[3] = &j;
}
void select(int idx)
{
(this->*pa[idx])();
}
private:
void f() {cout<<"void f()"<<endl;}
void g() {cout<<"void g()"<<endl;}
void i() {cout<<"void i()"<<endl;}
void j() {cout<<"void j()"<<endl;}
enum {cnt = 4};
void (Widget::*pa[cnt])() = {f, g, i, j};
};
//指向类成员函数的指针
int main()
{
Widget w;
w.select(0);
return 0;
}
友元Friend 破坏了封装性
成员函数变友元函数
#include <iostream>
#include <math.h>
using namespace std;
class Point
{
public:
Point(double xx, double yy)
{
x = xx;
y = yy;
}
friend double getDistance(Point & a, Point & b);
private:
double x, y;
};
double getDistance(Point & a, Point & b)
{
double dx = a.x - b.x;
double dy = a.y - b.y;
return sqrt(dx*dx + dy*dy);
}
int main()
{
Point p1(1, 2);
Point p2(3, 4);
double dis = getDistance(p1, p2);
cout<<dis<<endl;
return 0;
}
增加PointManagement 管理类
#include <iostream>
#include <math.h>
using namespace std;
class Point; //先声明类
class PointManagement
{
public:
double getDirectDistance(Point & a, Point & b); //两点间线段长度
double getTriDistance(Point & a, Point & b); //获得两点组成的三个边距离和
};
class Point
{
public:
Point(double xx, double yy)
{
x = xx;
y = yy;
}
friend double PointManagement::getDirectDistance(Point & a, Point & b);
friend double PointManagement::getTriDistance(Point & a, Point & b);
private:
double x, y;
};
double PointManagement::getDirectDistance(Point & a, Point & b)
{
double dx = a.x - b.x;
double dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
double PointManagement::getTriDistance(Point & a, Point & b)
{
double dx = a.x - b.x;
double dy = a.y - b.y;
c1 = sqrt(dx * dx + dy * dy);
return c1 + dx + dy;
}
int main()
{
Point p1(1, 2);
Point p2(3, 4);
double dis = getDistance(p1, p2);
cout<<dis<<endl;
return 0;
}
友元类:把一个类作为另一个类的友元
把A声明为B的友元,就可以通过B的变量访问B的private数据成员。
class Point
{
public:
Point(double xx, double yy)
{
x = xx;
y = yy;
}
friend class PointManagement; //友元类
private:
double x, y;
};
class PointManagement
{
public:
double getDirectDistance(Point & a, Point & b); //两点间线段长度
double getTriDistance(Point & a, Point & b); //获得两点组成的三个边距离和
};