引子:
C++认为万事万物皆为对象,对象有其属性和行为。
人可以作为对象,属性有姓名,年龄,身高,体重等,行为有行走,吃饭,唱歌等。
车也可以作为一个对象,属性有轮胎,方向盘,车灯等,行为有载人,放音乐等。
1.封装
1.1封装的意义
封装是是C++面向对象三大特性之一
封装的意义:
(1)将属性和行为作为一个整体,表现生活中的事物。
(2)将属性和行为加以权限控制。
1.1.1封装意义一:
在设计类的时候,属性和行为写在一起,表现事物。
语法:class 类名{ 访问权限:属性 / 行为 };
实例:设置一个长方体类,并求其体积
代码:
#include <iostream>
using namespace std;
class cuboid {
public:int height;int weight;int length;int show_tiji() {return height * weight * length;}
};
int main() {cuboid a1;a1.height = 10;a1.weight = 10;a1.length = 90;cout << a1.show_tiji();return 0;
}
1.1.2封装的意义二
类在设计时,可以把属性和行为放在不同权限下,加以控制
访问权限有三种:
1.public 公有权限,类内可以访问,类外可以访问
2.protected 保护权限,类内可以访问,类外不可以访问
3.private 私有权限,类内可以访问,类外不可以访问
代码:
#include <iostream>
using namespace std;
class people {
public:string name;
protected:string hose;
private:int m_Password;
public:void fun() {name = "小明";hose = "别墅";m_Password = 12345;}};
int main() {people a;a.fun();cout << a.name << endl;//cout << a.hose << endl; //报错//cout << a.m_Password << endl; //报错return 0;
}
1.2struct和class的区别
1.2.1默认权限不同
权限分为成员访问权限和继承权限
默认成员权限:class是私有的,struct是公有的
默认继承权限:class是private,struct是public
默认成员权限代码:
#include <iostream>
using namespace std;
class people1 {int a;
};
struct people2 {int a;
};
int main() {people1 a1;people2 a2;//a1.a = 100; //报错a2.a = 100;return 0;
}
默认继承权限代码:
#include <iostream>
using namespace std;
struct A {int m_a;
};struct B :A {int m_b;
};
int main() {B b;b.m_a = 100;return 0;
}
struct默认为公有继承;
#include <iostream>
using namespace std;
class A {
public:int m_a;
};class B :A {
public:int m_b;
};
int main() {B b;b.m_b = 100;//b.m_a = 100;return 0;
}
class默认私有继承
1.2.2能否定义模板参数
class可以定义模板参数 template<class T>,而没有template<struct T>
代码:
#include <iostream>
using namespace std;
//template< typename T, typename Y >
template< class T >
void Func(T& t,T& y)
{T temp = t;t = y;y = temp;
}int main() {int a = 10, b = 20;Func(a, b);cout << a << ' ' << b << endl;return 0;
}
1.2.3 class和struct相互继承
默认的继承属性取决于子类而不是基类
代码:
#include <iostream>
using namespace std;
class A {
public:int m_A;
};
struct B:A {int m_B;
};int main() {B b;b.m_A = 10;b.m_B = 20;cout << b.m_A <<' '<<b.m_B << endl;return 0;
}
struct作为子类,默认公有继承
代码:
#include <iostream>
using namespace std;
struct A {int m_A;
};
class B:A {
public:int m_B;
};int main() {B b;//b.m_A = 10; 报错b.m_B = 20;cout<<b.m_B << endl;return 0;
}
1.2.4{}赋初值的讨论
因为C++是对C的扩充,那么它就兼容过去C中struct的特性
#include <iostream>
using namespace std;
struct A
{char a1;int a2;double a3;
};int main() {A a = { 'p', 7, 451.154 }; //定义时赋初值,在struct时没问题,在class时出错return 0;
}
在struct中加入一个构造函数(或虚函数),struct也不能用{}赋值了,原因是以{}的方式来赋值,只是用一个初始化列表来对数据进行按顺序的初始化,如果上面写成A a = {‘p’,7};则a1,a2被初始化,而a3没有。这样简单的copy操作,只能发生在简单的数据结构上,而不应该放在对象上。加入一个构造函数或是一个虚函数会使strcut更体现出一种对象的特性,而是{}操作不再有效。因为加入这样的函数(构造和虚函数),使得类的内部结构发生了变化。而加入一个普通的成员函数呢?你会发现{}依旧可用。其实你可以将普通的函数理解成对数据结构的一种算法,这并不打破它数据结构的特性。
1.2.5总结
- 结构是实值类型(Value Types),而类则是引用类型(Reference Types)。
- 结构使用栈存储(Stack Allocation),而类使用堆存储(Heap Allocation)。
值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中。
概念:class和struct的语法基本相同,从声明到使用,都很相似,但是struct的约束要比class多,理论上,struct能做到的class都能做到,但class能做到的stuct却不一定做的到
类型:struct是值类型,class是引用类型,因此它们具有所有值类型和引用类型之间的差异
效率:由于栈的执行效率要比堆的执行效率高,但是栈资源却很有限,不适合处理逻辑复杂的大对象,因此struct常用来处理作为基类型对待的小对象,而class来处理某个商业逻辑
关系:struct不仅能继承也能被继承 ,而且可以实现接口,不过Class可以完全扩展。内部结构有区别,struct只能添加带参的构造函数,不能使用abstract和protected等修饰符,不能初始化实例字段
1.2.6选用技巧
(1) 在表示诸如点、矩形等主要用来存储数据的轻量级对象时,首选struct
(2) 在表示数据量大、逻辑复杂的大对象时,首选class
(3) 在表现抽象和多级别的对象层次时,class是最佳选择
1.3成员属性设置为私有化好处
1.3.1控制读写权限
可读可写权限,只读权限,只写权限
代码:
#include <iostream>
using namespace std;
class people {
public:void get_name(string name_1) {name = name_1; //写权限}string show_name() {return name; //读权限}void get_mima(string mima1) {mima = mima1; //写权限}int show_age() { //读权限return age;}
private://可读,可写string name;//只读int age;//只写string mima;};
int main() {people p;p.get_name("小明");cout << p.show_name() << endl;p.get_mima("56789");cout << p.show_age(); //没有设置,随机值return 0;
}
1.3.2写权限检测数据的有效性
代码:
#include <iostream>
using namespace std;
class people {
public:void get_name(string name_1) {name = name_1; //写权限}string show_name() {return name; //读权限}void get_mima(string mima1) {if (mima1.size() < 3) {cout << "密码太短,无效!" << endl;return;}mima = mima1; //写权限}int show_age() { //读权限return age;}
private://可读,可写string name;//只读int age;//只写string mima;};
int main() {people p;p.get_name("小明");cout << p.show_name() << endl;p.get_mima("59");cout << p.show_age(); //没有设置,随机值return 0;
}