桐柏微网站建设,企业公司网页,iis网站拒绝显示此网页,要做未来科技的网站怎么做类的性质
上文的例子中用到了类#xff0c;也知道了类的定义方法#xff0c;其实类还有更多的性质#xff0c;这些更多的性质完整支持了面向对象编程。
封装
以前说过#xff0c;程序就是数据和代码的组合。而C又正好提供了对数据的封装功能#xff0c;这就可以很好的完…类的性质
上文的例子中用到了类也知道了类的定义方法其实类还有更多的性质这些更多的性质完整支持了面向对象编程。
封装
以前说过程序就是数据和代码的组合。而C又正好提供了对数据的封装功能这就可以很好的完成数据和代码的组合。还是先上代码
#include stdlib.h
#include stdio.h
#include iostreamclass A
{
public:A(){_data 10;std::cout create A, _data is _data std::endl;}~A(){std::cout destory A std::endl;}void setData( int v ){_data v;}int getData()const{return _data;}protected:int _data;
};int main ( int argc, char *argv[] )
{A a;// 输出a中变量的值std::cout a._data is a.getData() std::endl;a.setData( 20 ); // 改变值为20std::cout a._data is a.getData() std::endl;A *a1 new A; // 动态创建A的另一个变量delete a1; // 删除这个变量这时候应该有输出destory Aa1 NULL;return 0;
}
编译后输出
create A, _data is 10
a._data is 10
a._data is 20
create A, _data is 10
destory A
destory A这段简单的代码定义了一个名叫A的类此类中有一个int类型的变量叫做_data这个变量的访问属性为protected说明在类的外部是无法访问此变量的。
构造函数
这个叫做A的类中有一个和类名相同的函数叫做A();这个函数叫做构造函数在定义A的变量时候被调用本例中在A a;和A *a1 new A这两行调用。
要注意构造函数没有返回类型。
如果没有手动定义构造函数C总是自动添加一个没有任何参数的默认构造函数如下代码
class B
{public:void setData(int v ){_data v;};int getData()const{return _data;};protected:int _data;
};这个例子中没有B的构造函数这时候_data没有被初始化则里面的值不确定。可以使用
B b;
std::cout b.getData() std::endl; 做个测试每次程序运行时都会输出不同的值。
除了不带参数的构造函数还可以再定义一个或多个带参数的构造当然函数名还是和类名相同如下代码
class C
{public:C(){ _data 0; };C( int v ){ _data v;};int getData()const{ return _data;};protected:int _data;
};int main( int argc, char *argv[] )
{C c;std::cout c.getData() std::endl;C c1(10);std::cout c1.getData() std::endl;return 0;
}
编译后输出
0
10可以看到C类有两个构造函数一个是默认构造函数一个是带参数的构造函数。带参数的构造函数把定义C时给的10放到了_data变量里。这时候就相当于给了另一个默认值10很多时候都会用到带参数的构造函数。
析构函数
回到最开始的例子可以看到还有另一个“~A()”这个函数叫做析构函数此函数会在清理掉A的变量时候被调用即被销毁的时候被调用。这个函数在类的定义过程中最多只有一个或是不定义析构函数这时候C编译器也会添加一个默认的什么功能也没有的析构函数。一般情况下需要定义这个析构函数用于清理一些自己创建的变量向第一个例子中main函数上一行中增加如下代码
class C
{
public:C(){_a new A;};~C(){delete _a;};protected:A *_a;};
// 修改main函数代码如下
int main ( int argc, char *argv[] )
{{C c;}return 0;
}
编译运行
create A, _data is 10
destory A可以看到变量_a的析构函数被调用也就是_a被销毁了。
修改代码注释掉 // ~C(){// delete _a;// };编译后再运行
create A, _data is 10这时可以看到_a的析构函数没有被调用。
其实在这里主要是_a的生成方式不同。在这里是用的new操作符动态创建的。一般使用new操作符分配的变量一定要在不用的时候配合delete操作符把分配的变量删除。C并不知道什么时候删除无用的变量一定要程序员手动添加删除代码。
成员函数
在定义类的变量的时候_data的访问属性是protected类型在上一节可以知道这种类型的变量无法在类的外部访问也就是没有办法直接使用这个变量为了能访问它在代码中添加了两个函数
setData此函数带一个参数函数内部用这个参数给_data新值。getData此函数功能更简单只是把_data值返回给调用者。
而getData和setData的访问属性为public也就是在类的外部可以调用。而在main函数中也确实是调用成功了。这样程序就有了修改类A中_data变量的方法但是也只能通过这两个函数来访问A中的变量。
到这里所谓的封装可能也就很清楚了。即隐藏数据提供访问方法。这样的思想在本例中可能很简单但是放到更复杂的代码环境中就会发现使用这种封装的方法管理数据在逻辑上非常清楚。
继承
所谓的继承也是面向对象编程中一个很重要的概念。先说一个为什么要继承。首先是在代码上可以重用再就是功能上可以扩展而再增加虚函数概念后会发现通过继承还能改变类的行为。虚函数这个东西以后再说本节先把继承搞清楚。 上一个简单的代码
#include stdlib.h
#include stdio.h
#include iostreamclass A
{
public:A(){_data 10;std::cout create A, _data is _data std::endl;}~A(){std::cout destory A std::endl;}void setData( int v ){_data v;};int getData()const{return _data;};protected:int _data;
};class C : public A
{
public:C(){_data2 0;}void setData2( int v ){_data2 v;};int getData2()const{return _data2;};int sum()const{return _data _data2;}
protected:int _data2;};int main ( int argc, char *argv[] )
{C c;c.getData();c.getData2();std::cout c.sum() std::endl;return 0;
}
观察代码可以看到本例中定义了两个类 A和C。 其中C的定义后面有 “public A”。 这就是表示类C是从类A继承而来。 而“public”表示此继承是公有继承同样“public”可以换成protecte和private。在本例中不能换换后的效果可以自己做测试。 然后在main函数中定义了一个C的变量c。 这时候使用此c变量可以成功调用A的getData函数和自己的getData2函数。说明类C拥有了类A的功能这就是对类A功能的继承同样里面的数据也一起继承了过来即在C中可以直接操作A的成员变量_data。
因为继承这种从上到下的关系一般会把A叫做C的父类, 类关系图如下 #mermaid-svg-Zwv33csMmDWR4KF9 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Zwv33csMmDWR4KF9 .error-icon{fill:#552222;}#mermaid-svg-Zwv33csMmDWR4KF9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Zwv33csMmDWR4KF9 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-Zwv33csMmDWR4KF9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Zwv33csMmDWR4KF9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Zwv33csMmDWR4KF9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Zwv33csMmDWR4KF9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Zwv33csMmDWR4KF9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Zwv33csMmDWR4KF9 .marker.cross{stroke:#333333;}#mermaid-svg-Zwv33csMmDWR4KF9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Zwv33csMmDWR4KF9 g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-Zwv33csMmDWR4KF9 g.classGroup text .title{font-weight:bolder;}#mermaid-svg-Zwv33csMmDWR4KF9 .nodeLabel,#mermaid-svg-Zwv33csMmDWR4KF9 .edgeLabel{color:#131300;}#mermaid-svg-Zwv33csMmDWR4KF9 .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-Zwv33csMmDWR4KF9 .label text{fill:#131300;}#mermaid-svg-Zwv33csMmDWR4KF9 .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-Zwv33csMmDWR4KF9 .classTitle{font-weight:bolder;}#mermaid-svg-Zwv33csMmDWR4KF9 .node rect,#mermaid-svg-Zwv33csMmDWR4KF9 .node circle,#mermaid-svg-Zwv33csMmDWR4KF9 .node ellipse,#mermaid-svg-Zwv33csMmDWR4KF9 .node polygon,#mermaid-svg-Zwv33csMmDWR4KF9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Zwv33csMmDWR4KF9 .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-Zwv33csMmDWR4KF9 g.clickable{cursor:pointer;}#mermaid-svg-Zwv33csMmDWR4KF9 g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Zwv33csMmDWR4KF9 g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Zwv33csMmDWR4KF9 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Zwv33csMmDWR4KF9 .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-Zwv33csMmDWR4KF9 .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Zwv33csMmDWR4KF9 .dashed-line{stroke-dasharray:3;}#mermaid-svg-Zwv33csMmDWR4KF9 #compositionStart,#mermaid-svg-Zwv33csMmDWR4KF9 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Zwv33csMmDWR4KF9 #compositionEnd,#mermaid-svg-Zwv33csMmDWR4KF9 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Zwv33csMmDWR4KF9 #dependencyStart,#mermaid-svg-Zwv33csMmDWR4KF9 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Zwv33csMmDWR4KF9 #dependencyStart,#mermaid-svg-Zwv33csMmDWR4KF9 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Zwv33csMmDWR4KF9 #extensionStart,#mermaid-svg-Zwv33csMmDWR4KF9 .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Zwv33csMmDWR4KF9 #extensionEnd,#mermaid-svg-Zwv33csMmDWR4KF9 .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Zwv33csMmDWR4KF9 #aggregationStart,#mermaid-svg-Zwv33csMmDWR4KF9 .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Zwv33csMmDWR4KF9 #aggregationEnd,#mermaid-svg-Zwv33csMmDWR4KF9 .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Zwv33csMmDWR4KF9 .edgeTerminals{font-size:11px;}#mermaid-svg-Zwv33csMmDWR4KF9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} A - _data A() setData() getData() C - _data2 C() setData2() getData2() 多态
在初识C程序前面的代码例子中已经看到过virtual这个关键字。当时是为了让某个函数有和父类函数不同的功能而添加。
虚函数
使用virtual修饰的类的函数叫做虚函数父类中的虚函数可以由子类重新实现这样在外部调用时会找到子类的虚函数定义。 虚函数又分为两种普通虚函数纯虚函数比如下面两个类的定义
class A
{public:A(){};virtual void fun(){printf(from a fun\n);};
};
class B : public A
{public:B(){};virtual void fun(){printf(from b fun\n);};
}在这里B类的fun函数会覆盖掉A的fun函数。如下的调用方式 A *lpA new B;lpA-fun(); // 这里调用的是B的fun函数虽然是用的A类型的指针但是最终也是调用B的fun函数。A *lpA2 new A;lpA2-fun(); // 这里调用的是A的fun函数。需要注意的是只要父类中的任何一个函数声明为虚函数则子类中不管是否使用virtual修饰同样的函数此函数都一直是虚函数。
虚函数的使用
更多的时候虚函数的定义是为了提供一致的函数调用方法也叫做定义接口。大多数时候程序员的工作是为了提供一个运行框架而更多的功能是围绕这个框架添加这时一致的接口调用就非常重要在C的时候程序员可能会用函数指针来解决这个问题。而C语言提供了虚函数这个特性那么在不修改主框架代码的情况下偷偷的替换里面的某一段代码功能就成为可能比如下面这种情况
#include stdlib.h
#include stdio.h
#include iostreamclass Computer
{public:Computer(){_a 0;_b 0;}void setA( int a ){_a a;}void setB( int b ){_b b;}virtual void work(){printf(use Computer work\n);_r _a _b;};void printResult(){printf(%d\n, _r);}protected:int _a;int _b;int _r;
};class Computer2 : public Computer
{public:Computer2(){}virtual void work(){printf(use Computer2 work\n);_r _a * _b;}};int main ( int argc, char *argv[] )
{std::string workType argv[1];Computer *lpComputer NULL;int a 10;int b 3;if ( workType 2 ){lpComputer new Computer2( );}else{lpComputer new Computer( );}lpComputer-setA( a );lpComputer-setB( b );lpComputer-work();lpComputer-printResult();delete lpComputer;return 0;
}
编译运行
$ ./virtualclass.exe 1
use Computer work
13AdministratorWIN-R9MT13JQHOK /e/workspace/book
$ ./virtualclass.exe 2
use Computer2 work
30第一次运行时给程序带了一个外部参数“1”第二次运行时给程序带了一个部分参数“2”。最终得到了两个不同的输出。 此代码在main函数中还能看到是通过判断不同的输入而生成了不同Computer实例。在这里表现的并不明显可以接着做个改进把创建Computer指针的代码封装成一个函数如下
Computer *createComputer( std::string const t )
{Computer *lpComputer NULL;if ( t 2 ){lpComputer new Computer2( a, b );}else{lpComputer new Computer( a, b );}return lpComputer;
}int main ( int argc, char *argv[] )
{std::string workType argv[1];Computer *lpComputer createComputer( workType );int a 10;int b 3;lpComputer-setA( a );lpComputer-setB( b );lpComputer-work();lpComputer-printResult();return 0;
}
在这个例子中main函数的工作过程不变但是当要切换计算方法时还是只要给出不同的工作类型2或是1就能让main函数的工作方式完全改变。 这时候如果再给一个新的工作方式“3”只需要修改createComputer的实现而不用修改主函数的任何代码。这个结构就给了对程序进行动态扩展的能力。比如把createComputer这个函数和计算类放到另一个动态库中由其他人开发这个动态库他只要在有新的功能时把这个动态库更新就可以给整个程序做功能升级。
纯虚函数的使用
纯虚函数的定义方法如下
class A
{public:A(){};virtual void fun() 0;
}这时候不能直接定义类A的变量只能定义指针 A a;///这一行在编译时报错.A *lpA NULL;// 这一行可以正确编译在多数情况下纯虚函数只是为了规范一系列类的接口比如有一个文件操作类 class File{public:File(){};virtual ~File(){};virtual bool open() 0; //打开文件virtual bool close() 0;//关闭文件virtual bool write() 0;//写文件 virtual bool read() 0;//读文件};这样一个文件操作类使用者只知道这个类有四个可用的功能函数而每个函数的具体实现就要根据文件类型分别实现。使用者能做的就是使用文件指针调用这几个函数完成文件操作功能而不必关心里面的实现这在一定程度上也把程序的复杂度降了下来又对细节做了封装隔离。 一般来说对它会有如下简单的扩展 #mermaid-svg-BFOtB0a4GGelbDsk {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-BFOtB0a4GGelbDsk .error-icon{fill:#552222;}#mermaid-svg-BFOtB0a4GGelbDsk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BFOtB0a4GGelbDsk .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-BFOtB0a4GGelbDsk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BFOtB0a4GGelbDsk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BFOtB0a4GGelbDsk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BFOtB0a4GGelbDsk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BFOtB0a4GGelbDsk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BFOtB0a4GGelbDsk .marker.cross{stroke:#333333;}#mermaid-svg-BFOtB0a4GGelbDsk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BFOtB0a4GGelbDsk g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-BFOtB0a4GGelbDsk g.classGroup text .title{font-weight:bolder;}#mermaid-svg-BFOtB0a4GGelbDsk .nodeLabel,#mermaid-svg-BFOtB0a4GGelbDsk .edgeLabel{color:#131300;}#mermaid-svg-BFOtB0a4GGelbDsk .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-BFOtB0a4GGelbDsk .label text{fill:#131300;}#mermaid-svg-BFOtB0a4GGelbDsk .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-BFOtB0a4GGelbDsk .classTitle{font-weight:bolder;}#mermaid-svg-BFOtB0a4GGelbDsk .node rect,#mermaid-svg-BFOtB0a4GGelbDsk .node circle,#mermaid-svg-BFOtB0a4GGelbDsk .node ellipse,#mermaid-svg-BFOtB0a4GGelbDsk .node polygon,#mermaid-svg-BFOtB0a4GGelbDsk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BFOtB0a4GGelbDsk .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-BFOtB0a4GGelbDsk g.clickable{cursor:pointer;}#mermaid-svg-BFOtB0a4GGelbDsk g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-BFOtB0a4GGelbDsk g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-BFOtB0a4GGelbDsk .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-BFOtB0a4GGelbDsk .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-BFOtB0a4GGelbDsk .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-BFOtB0a4GGelbDsk .dashed-line{stroke-dasharray:3;}#mermaid-svg-BFOtB0a4GGelbDsk #compositionStart,#mermaid-svg-BFOtB0a4GGelbDsk .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-BFOtB0a4GGelbDsk #compositionEnd,#mermaid-svg-BFOtB0a4GGelbDsk .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-BFOtB0a4GGelbDsk #dependencyStart,#mermaid-svg-BFOtB0a4GGelbDsk .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-BFOtB0a4GGelbDsk #dependencyStart,#mermaid-svg-BFOtB0a4GGelbDsk .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-BFOtB0a4GGelbDsk #extensionStart,#mermaid-svg-BFOtB0a4GGelbDsk .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-BFOtB0a4GGelbDsk #extensionEnd,#mermaid-svg-BFOtB0a4GGelbDsk .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-BFOtB0a4GGelbDsk #aggregationStart,#mermaid-svg-BFOtB0a4GGelbDsk .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-BFOtB0a4GGelbDsk #aggregationEnd,#mermaid-svg-BFOtB0a4GGelbDsk .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-BFOtB0a4GGelbDsk .edgeTerminals{font-size:11px;}#mermaid-svg-BFOtB0a4GGelbDsk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} File open() close() write() read() TxtFile open() close() write() read() ImgFile open() close() write() read() XMLFile open() close() write() read() 使用这种方法隔离实现细节。
到这里面向对象编程的三个常用的特性就都介绍完了再重复一次 #mermaid-svg-edxW4z4jsWVmttY1 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-edxW4z4jsWVmttY1 .error-icon{fill:#552222;}#mermaid-svg-edxW4z4jsWVmttY1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-edxW4z4jsWVmttY1 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-edxW4z4jsWVmttY1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-edxW4z4jsWVmttY1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-edxW4z4jsWVmttY1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-edxW4z4jsWVmttY1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-edxW4z4jsWVmttY1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-edxW4z4jsWVmttY1 .marker.cross{stroke:#333333;}#mermaid-svg-edxW4z4jsWVmttY1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-edxW4z4jsWVmttY1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-edxW4z4jsWVmttY1 .cluster-label text{fill:#333;}#mermaid-svg-edxW4z4jsWVmttY1 .cluster-label span{color:#333;}#mermaid-svg-edxW4z4jsWVmttY1 .label text,#mermaid-svg-edxW4z4jsWVmttY1 span{fill:#333;color:#333;}#mermaid-svg-edxW4z4jsWVmttY1 .node rect,#mermaid-svg-edxW4z4jsWVmttY1 .node circle,#mermaid-svg-edxW4z4jsWVmttY1 .node ellipse,#mermaid-svg-edxW4z4jsWVmttY1 .node polygon,#mermaid-svg-edxW4z4jsWVmttY1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-edxW4z4jsWVmttY1 .node .label{text-align:center;}#mermaid-svg-edxW4z4jsWVmttY1 .node.clickable{cursor:pointer;}#mermaid-svg-edxW4z4jsWVmttY1 .arrowheadPath{fill:#333333;}#mermaid-svg-edxW4z4jsWVmttY1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-edxW4z4jsWVmttY1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-edxW4z4jsWVmttY1 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-edxW4z4jsWVmttY1 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-edxW4z4jsWVmttY1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-edxW4z4jsWVmttY1 .cluster text{fill:#333;}#mermaid-svg-edxW4z4jsWVmttY1 .cluster span{color:#333;}#mermaid-svg-edxW4z4jsWVmttY1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-edxW4z4jsWVmttY1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 面向对象编程 封装 继承 多态 如果学过C语言就会知道在C语言中也可以自定义数据结构就是使用叫做struct的关键字。在C里面可以把struct看成是所有内容都是public属性的类。