1. 封装
1.1. struct
当单一变量无法完成描述需求的时候,结构体类型解决了这一问题。可以将多个类型打包成一体,形成新的类型,这是c语言中的封装
但是,新类型并不包含,对数据类的操作。所有操作都是通过函数的方式进行封装的
struct Date
// c语言的封装 数据放到 一起用struct打包,然后把数据以引用或指针的方式传给行为
// c++认为c语言封装不彻底
// 数据和行为分离,没有权限控制 对内数据开放,逻辑抽象,对外提供接口
struct Date
{
int year;
int month;
int day;
};
void init(Date &d)
{
cin >> d.year >> d.month >> d.day;
}
void print(Date &d)
{
cout << d.year << " " << d.month << " " << d.day << endl;
}
bool isLeapYear(Date &d)
{
if (d.year % 4 == 0 || d.year % 400 == 0 && d.year % 100 != 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;
}
1.2. 封装
封装,可以实现对外提供接口,屏蔽数据,对内开放数据
比如:用struct封装的类,既知其接口,又可以直接访问其内部数据,这样却没有达到信息隐蔽的功效,而class则提供了这样的功能,屏蔽内部数据,对外开放接口
struct中所有行为和属性都是public的(默认),c++中class可以指定行为和属性的访问方式,默认为private
1.3. 用class封装带行为的类
class封装的本质,在于将数据和行为,绑定在一起通过对象来完成操作
class Date
// 权限控制 private protected public
// 数据和行为在一起
// 对内开放数据,逻辑抽象,对外提供接口
// 类 类对象 对象,调用行为完成需求
class Date
{
public:
void init()
{
cin >> year >> month >> day;
}
void print()
{
cout << "year:" << "month:" << "day" << endl;
cout << year << month << day << endl;
}
bool isLeapYear()
{
if (year % 4 == 0 || year % 400 == 0 && year % 100 != 0)
return true;
else
return false;
}
int getYear()
{
return year;
}
protected:
int year;
private:
int month;
int day;
};
int main()
{
Date d;
// d.year = 3000; // private
d.init();
d.print();
if (d.isLeapYear())
cout << d.getYear() << " is leap year" << endl;
else
cout << d.getYear() << " is not leap year" << endl;
return 0;
}
Date类访问自己的成员,可以不需要通过传引用的方式
class Date
{
public:
void init(); // 函数成员
void print();
bool isLeapYear();
int getYear();
protected:
int year;
private:
int month; // 数据成员
int day;
};
void Date::init()
{
cin >> year >> month >> day;
}
void Date::print()
{
cout << "year:" << "month:" << "day" << endl;
cout << year << month << day << endl;
}
bool Date::isLeapYear()
{
if (year % 4 == 0 || year % 400 == 0 && year % 100 != 0)
return true;
else
return false;
}
int Date::getYear()
{
return year;
}
int main()
{
Date d;
// d.year = 3000; // private
d.init();
d.print();
if (d.isLeapYear())
cout << d.getYear() << " is leap year" << endl;
else
cout << d.getYear() << " is not leap year" << endl;
return 0;
}
date.h
#ifndef DATE_H
#define DATE_H
// 类名其实也是一种变相的命名空间
namespace Space
{
class Date
{
public:
void init(); // 函数成员
void print();
bool isLeapYear();
int getYear();
protected:
int year;
private:
int month; // 数据成员
int day;
};
}
#endif
date.cpp
#include "date.h"
#include <iostream>
using namespace std;
namespace Space
{
void Date::init()
{
cin >> year >> month >> day;
}
void Date::print()
{
cout << "year:" << "month:" << "day" << endl;
cout << year << month << day << endl;
}
bool Date::isLeapYear()
{
if (year % 4 == 0 || year % 400 == 0 && year % 100 != 0)
return true;
else
return false;
}
int Date::getYear()
{
return year;
}
}
main.cpp
// 声明和实现要分开
#include "date.h"
using namespace Space;
int main()
{
Date d;
// d.year = 3000; // private
d.init();
d.print();
if (d.isLeapYear())
cout << d.getYear() << " is leap year" << endl;
else
cout << d.getYear() << " is not leap year" << endl;
return 0;
}
2. 练习封装
2.1. 封装自己的list
main.cpp
class List
{
public:
List *createList();
void insertList(int d);
void traverseList();
private:
struct Node
{
int data;
struct Node *next;
} *head;
};
List *List::createList()
{
head = new Node;
head->next = NULL;
return this;
}
void List::insertList(int d)
{
Node *cur = new Node;
cur->data = d;
cur->next = head->next;
head->next = cur;
}
void List::traverseList()
{
Node *ph = head->next;
while (ph != NULL)
{
cout << ph->data << endl;
ph = ph->next;
}
}
int main()
{
List list;
list.createList();
for (int i = 0; i < 10; i++)
{
list.insertList(i);
}
list.traverseList();
return 0;
}