1.类成员
#include<iostream>
using namespace std;
//初始化参数列表:真正初始化类成员的地方,const成员的初始化必须在初始化及逆行
//普通成员也可以进性初始化,多个成员必须用逗号分隔开
//初始化成员的顺序,是成员在类中声明的先后的顺序
/*
*编译器是指把源程序交给编译器编译生成的过程,最终得到可执行的文件
* 运行期是指将可执行文件交给操作系统执行,直到程序退出,执行的目的是为了实现程序的功能
* 类是编译器的概念。包括成员的访问控制和作用域
* 对象是运行期的概念,包括定义类的实例,引用,指针等使用其他类成员
*/
class CTEST
{
public:
mutable int m_a;//可以打破常函数的限制,可以在长函数中进行赋值
const int m_b;
CTEST() :m_a(10), m_b(20)//对参数进行初始值
{
}
CTEST(int a) :m_a(a), m_b(m_a)//对参数进行初始值
{
}
/*
* const int m_b;
* int m_a;
* CTEST(int a) :m_a(a), m_b(m_a)//这种情况对声明位置变换一下
就导致赋值的时候,也是先对m_b进行初始化,后对m_a进行初始化
*/
void play(/*CTEST * CONTS THIS*/)//里面修饰的是一个this指针,
用这个this指针去指向对象的内容
{
this->m_a = 20;
}
void show (/* const CTEST * CONTS THIS */) const
//参数列表中的const是用来修饰this指针的
{
//m_a = 20;// int m_a; 没有办法修改外部的值
this->m_a = 20;
cout << m_a << endl;
}
};
int main01()
{
const CTEST tst;
tst.show();
//tst.play();//CTest *const this =&tst; 指针安全级别降低 不允许进行
//
CTEST tst2;
tst2.show();//const CTest * const this =&tst2; 指针安全级别升级,允许
tst2.play();//同一级别,也可以进行使用
//const int a = 10;//定义了就要进行初始化
//int b = 20;
//const int* p1 = &a;//常量指针 const修饰的是*p
*p1=10;//违法 *p1指向的空间已经是锁死的,不能在进行赋值
//cout << *p1 << endl;//能够进行读取
//p1 = &b;//合法,可以修改指向的空间
//
//int* const p2 = &b;//指针常量 const修饰的p指针
//*p2 = 30;//可以通过指针修改里面的值
//cout << *p2 << endl;
int *const p3=&a;//这种不合法,a的类型与p3的冲突
}
2.内联
#include <iostream >
using namespace std;
/*
内联:inline
是一种空间换时间的做法,提高了函数的执行效率,但并不是所有函数都可以成为内联函数。代码较长,内部循环等都不应该成为内联
定义inline只是一种建议,但是编译器并不一订会直接用,并不是强制性的,编译器有自己的判断能力,会根据实际情况判断是否是内联函数,编译器不会把递归函数视为内联函数
类,结构中的类内部声明并定义的函数视为内联函数,如果类中只给出声明,在类外定义的函数,那么默认不是内敛,除非我们手动加上inline关键字
*/
class Ctest
{
public:
int getshow()
{
char arr[20] = { 0 };
//cout << &Ctest::show << endl;//用来得到show函数的地址,用::说明其作用域
printf("%p", &Ctest::show);
sprintf(arr, "%d", &Ctest::show);
return atoi(arr);//进行进制的转换
}
private:
int m_a;
void show()
{
cout << "show" << endl;
}
};
union AA
{
int a;
void (*p_fun)();
};
int a = 10;
static int b = 10;//编译器就已经存在
//inline//关键字:内联
//优点,执行效率提升了
inline int add(int a, int b)
{
return a + b;//通过增加空间,来减少时间,系统中使用的越多,占据的内存空间就越大
}
int main()
{
Ctest tst;
AA aa;
aa.a=tst.getshow();
//new //运行的时候才有
}
3.类之间的横向关系
1.复合,一个类中有另一个对象,必须拥有的,生命周期相同
2.依赖,类似于外部工具,使用的一种工具,可以利用参数进行调用
3.关联:类中定义了关于另一个类的指针,通过指针进行调用
4.聚合:多个对象被当作成一个整体
#include <iostream>
using namespace std;
/*
1.复合,组合:组合中一个类中包含另一个类对象,是一种强所属关系,组合的对象具有同样的生命周期,
整体不存在,部分就不一定存在。就是人和手的关系
2.依赖,下例中的电脑就是依赖,我们需要进行什么功能的时候,需要借助外部的工具。依赖之间没有什么生命周期的约束。
就是需要的时候用,不需要的时候,也不用存在,不像是人手,必须是时刻存在
通常被以来的的对象是另一类方法的参数的形式实现俩个类之间的依赖关系
3.关联:平等关系。完成某个功能与某个有关,可有可无,俩者没有生命周期的约束,被关联对象的生命周期由谁创建,就有谁维护,可以随时进行解除关系,
通常在关联类中定义被关联对象的指针,实现关联
4.聚合:多个被聚合的对象,聚集起来刑场大的整体,被聚合的对象还可以再被别的对象关联
通常在聚合类中定义被聚合对象指针的容器
*/
class action
{
public:
void paly()
{
cout << "移动手脚" << endl;
}
};
class Computer
{
public:
void program()
{
cout << "进行编程" << endl;
}
};
class Cfrienf
{
public:
void play_together()
{
cout << "一起来玩啊" << endl;
}
};
class cpeople
{
public:
action move_hand;//是一种复合关系,一个类中包含另一个类
Cfrienf* friend_ptr;
cpeople()
{
friend_ptr = nullptr;
}
void show()
{
cout << "我要开始移动了" << endl;
}
void run(Computer* ptr)
{
if (ptr)
{
ptr->program();
}
}
void frienf_play()
{
if (friend_ptr)
{
friend_ptr->play_together();
}
else
{
cout << "自己玩吧" << endl;
}
}
};
class famliy
{
public:
cpeople* people[10];
famliy()
{
for (int i = 0; i < 10; i++)
{
people[i] = nullptr;
}
people[0] = new cpeople;
people[1] = new cpeople;
people[2] = new cpeople;
}
~famliy()
{
for (int i = 0; i < 10; i++)
{
if (people[i])
{
delete people[i];
people[i] = nullptr;
}
}
}
void allpeople(Computer *com_str)
{
for (int i = 0; i < 10; i++)
{
if (people[i])
{
people[i]->run(com_str);
}
}
}
};
int main01()
{
//-------复合
cpeople man;
man.move_hand.paly();
//-------依赖
Computer* str = new Computer;
man.run(str);
delete str;
//-------关联
cpeople playman;
Cfrienf friend1;
playman.friend_ptr = &friend1;
playman.frienf_play();
//-----聚合
famliy fai;
Computer* ptr = new Computer;
fai.allpeople(ptr);
return 0;
}
4.纵向关系
纵向,父子类
#include <iostream>
using namespace std;
//纵向关系,继承
//父类(基类)
class father
{
public:
int a = 10;
void show()
{
cout << "father" << endl;
}
};
//子类(派生类)
class son :public father
{
public:
int b = 20;
void show()
{
cout << "son" << endl;
}
};
//子类以及父类之间的同名,利用::进行区别
int main()
{
father fa_1;
son son_1;
cout << son_1.a << endl;
cout << son_1.b << endl;
son_1.show();
son_1.father::show();
fa_1.show();
}
5.继承
#include <iostream>
using namespace std;
class Cfather
{
public:
int m_a;
int money;
Cfather()
{
m_a = 10;
money = 20;
}
Cfather(int a, int b)
{
m_a = a;
money = b;
}
void play(int a,int b,int c)
{
cout << a << b << c << endl;
}
private:
int p_a = 10;
};
class Cson :public Cfather
{
public:
int m_b;
int money;
Cfather fa;
/*Cson():Cfather()//当父类是无参构造的时候,:Cfather()写不写都行,没写程序会自动默认
{
m_b = 10;
money = 20;
}*/
Cson(int a,int b):Cfather(a,b),fa(10,20)//当父类中构造函数有参数的时候,必须在子类中进行说明//增加一个父类对象,进行赋值
{
m_b = a;
money = b;
}
void play(int a, int b)//子类中跟父类中的重名的函数,子类中的函数会覆盖父类中的函数,没有办法自动区分,如果要使用父类中的需要加作用域声明
{
cout << a << b << endl;
}
private:
};
class Csonson :public Cson
{
};
/*
* 在对象创建的时候,先将父类中的进行定义,在对子类中的数据进行赋值,父类中的无参构造可以自动被调用
* 如果父类中的是有参构造,那么需要在子类中进行类的参数构造,并且是先构造父类,在构造子类
* 子类对象中,进行析构函数的时候,先进行子类析构,在进行父类的析构
* 父类构建->子类构建 子类析构<-父类对象析构<-父类析构
*/
/*
* //继承方式: 描述了 父类的成员在子类所表现的属性,
//public: 公有继承:
//父类 子类
//public public
//protected protected
//private 不可访问
//
//protected: 保护继承:
//父类 子类
//public protected
//protected protected
//private 不可访问
//
//private: 私有继承:
//父类 子类
//public private
//protected private
//private 不可访问
*/
/*
继承的好处:将一些功能类似的公共成员,给单独抽离出来,单独成一个类
这个类就是父类,继承父类,包含了这些公共的成员
提高了程序代码的复用性,扩展性,后期更容易维护
*/
int main()
{
Cson son(1,2);
cout << son.m_a << " " << son.Cfather::money << " " << son.m_b << " " << son.money << endl;
cout << &son.m_a << " " << &son.Cfather::money << " " << &son.m_b << " " << &son.money << endl;
cout << son.fa.m_a << endl;
son.play(1,2);
son.Cfather::play(1, 2, 3);
return 0;
}