关于C++类的排列组合分组问题的问题

APLA组合数据类型的C++实现
Implementation of Composed Data Type in APLA Through C++
江西师范大学
计算机软件与理论
PAR方法,RADL语言,APLA语言,程序转换
英文关键词
PARmethod,RADL,APLA,C++classlibrary,programtransform
随着科技进步和社会生产力的发展,计算机软件的重要性与日俱增,但至今软件产品仍普遍存在着可靠性难以确保,生产效率低等问题。由此,软件故障给人类造成的危害越来越大,软件产品的生产也远远满足不了人们的需要。如何快速高效地开发出具有高可靠性的软件系统,成为软件开发人员长期思考的问题,也是软件产业得以迅速发展的关键。
为了改变软件发展的现状,提高软件产品的可靠性,薛锦云教授在多个国家级课题的资助下提出了一种普遍适用的算法程序形式化开发方法——PAR方法,开辟了程序设计的新途径。
本文是PAR方法的重要组成部分,也是国家自然科学基金课题“实用的软件形式化方法及其开发工具研究”的重要内容。本项研究的主要目标是正确地实现APLA语言中的抽象数据类型,具体研究内容为:
1.对目前的程序设计方法(包括形式化方法和非形式化方法)进行分析研究,寻找一种合适的方法帮助我们正确地实现APLA语言中的抽象数据类型;
2.利用PAR方法,以自扩展的方式正确地实现APLA语言定义的抽象数据类型;
3.通过对泛型程序设计思想的研究,在我们构造的C++类库中引进了泛型程序机制,实现了APLA程序的类型参数化,同时也提高了C++类库的可重用程度;
4.通过大量测试用例(由APLA-C++转换器转换而来的C++程序)对所构造的C++类库进行了进一步测试。
本文还用PAR方法和上述的APLA-C++转换工具开发了一些算法。
利用PAR方法自扩展生成的C++类库与APLA-C++转换器共同组成具有高可靠性的APLA-C++自动转换系统,成功地转换了大量的实例,并得到了正确的结果。
With the improvement of science and social productivity,software has become more and more important during the forty years. But the efficiency of developing software is very low. Moreover,software products still have many defaults universally up to the present. For example,the quality is not good and the reliability can’t be guaranteed totally. Consequently,the harm brought by the defaults in software is becoming more serious,and the amount of software products can’t keep the pace with the needs of people. How to work out the programs with high reliability has troubled the developer for a long time,which is also the key to the rapid development of software industry.In order to modify the current situation of software development,improving the reliability of the products,Pro. Xue put forward a generally accommodated method -PAR method which create a new approach for programming.The thesis,which is a important part of the PAR method,is the important content of the project supported by the National Natural Science Foundation of China-'The research of a practical formal developing method and its tools'. Its main target is correct realization of the abstract data in APLA,and its main content is:1.
By analyzing the current methods of programming,including formal methods and informal methods,we found a suitable approach which can help us to realize abstract data in APLA correctly.2.
By using the PAR method and transforming system,we implement the abstract data in APLA correctly.3. We import the generic programming theory into the C++ class library through studying the idea of generic programming,achieve the generic programming in APLA program.4. We also test the C++ class library by many examples what are transformed by APLA-C++ system. In addition,we also develop any algorithm program by using the PAR method and the transformingsystem.The C++ class library and APLA-C++ transforming machine compose the APLA-C++ system with high reliability,which has transformed many examples correctly,and the running results are correct.鸡啄米:C++编程入门系列之十五(类与对象:类的组合)
&&&&&&&上一讲鸡啄米给大家讲了,让大家了解了类的创建和释放过程。这一节讲讲类的组合。&&&&&&&在我们对现实中的某些事物抽象成类时,可能会形成很复杂的类,为了更简洁的进行软件开发,我们经常把其中相对比较独立的部分拿出来定义成一个个简单的类,这些比较简单的类又可以分出更简单的类,最后由这些简单的类再组成我们想要的类。比如,我们想要创建一个计算机系统的类,首先计算机由硬件和软件组成,硬件又分为CPU、存储器等,软件分为系统软件和应用软件,如果我们直接创建这个类是不是很复杂?这时候我们就可以将CPU写一个类,存储器写一个类,其他硬件每个都写一个类,硬件类就是所有这些类的组合,软件也是一样,也能做成一个类的组合。计算机类又是硬件类和软件类的组合。&&&&&& 类的组合其实描述的就是在一个类里内嵌了其他类的对象作为成员的情况,它们之间的关系是一种包含与被包含的关系。简单说,一个类中有若干数据成员是其他类的对象。以前的教程中我们看到的类的数据成员都是基本数据类型的或自定义数据类型的,比如int、float类型的或结构体类型的,现在我们知道了,数据成员也可以是类类型的。&&&&&& 如果在一个类中内嵌了其他类的对象,那么创建这个类的对象时,其中的内嵌对象也会被自动创建。因为内嵌对象是组合类的对象的一部分,所以在构造组合类的对象时不但要对基本数据类型的成员进行初始化,还要对内嵌对象成员进行初始化。&&&&&& 组合类构造函数定义(注意不是声明)的一般形式为:&&&&&& 类名::类名(形参表):内嵌对象1(形参表),内嵌对象2(形参表),...&&&&& &{&&&&&&&&&&&&&&& &类的初始化&&&&& &}&&&&&& 其中,“内嵌对象1(形参表),内嵌对象2(形参表),...”成为初始化列表,可以用于完成对内嵌对象的初始化。其实,一般的数据成员也可以这样初始化,就是把这里的内嵌对象都换成一般的数据成员,后面的形参表换成用来的初始化一般数据成员的变量形参,比如,Point::Point(int xx, int yy):X(xx),Y(yy) { },这个定义应该怎么理解呢?就是我们在构造Point类的对象时传入实参初始化xx和yy,然后用xx的值初始化Point类的数据成员X,用yy的值初始化数据成员Y。&&&& &&声明一个组合类的对象时,不仅它自身的构造函数会被调用,还会调用其内嵌对象的构造函数。那么,这些构造函数的调用是什么顺序呢?首先,根据前面说的初始化列表,按照内嵌对象在组合类的声明中出现的次序,依次调用内嵌对象的构造函数,然后再执行本类的构造函数的函数体。比如下面例子中对于Distance类中的p1和p2就是先调用p1的构造函数,再调用p2的构造函数。因为Point p1,p2;是先声明的p1后声明的p2。最后才是执行Distance构造函数的函数体。&&&&& &如果声明组合类的对象时没有指定对象的初始值的话,就会自动调用无形参的构造函数,构造内嵌对象时也会对应的调用内嵌对象的无形参的构造函数。析构函数的执行顺序与构造函数正好相反。&&&&& &这里鸡啄米给大家一个类的组合的例子,其中,Distance类就是组合类,可以计算两个点的距离,它包含了Point类的两个对象p1和p2。&&&&&&&#include&&iostream&
&&&&&&&using&namespace&
&&&&&&&class&Point
&&&&&&&{&
&&&&&&&public:
&&&&&&&&&&&&&&&&&Point(int&xx,int&yy)&&&{&X=&Y=&}&//构造函数
&&&&&&&&&&&&&&&&&Point(Point&&p);
&&&&&&&&&&&&&&&&&int&GetX(void)&&&&&{&return&X;&}&&&&&&&&//取X坐标
&&&&&&&&&&&&&&&&&int&GetY(void)&&&&&{&return&Y;&}&//取Y坐标
&&&&&&&private:
&&&&&&&&&&&&&&&&&int&X,Y;&//点的坐标
&&&&&&&};
&&&&&&&Point::Point(Point&&p)
&&&&&&&{
&&&&&&&&&&&&&&&&&X&=&p.X;
&&&&&&&&&&&&&&&&&Y&=&p.Y;
&&&&&&&&&&&&&&&&&cout&&&&&Point拷贝构造函数被调用&&&&&
&&&&&&&}
&&&&&&&class&Distance
&&&&&&&{
&&&&&&&public:
&&&&&&&&&&&&&&&&Distance(Point&a,Point&b);&//构造函数
&&&&&&&&&&&&&&&&double&GetDis()&&&{&return&&}
&&&&&&&private:
&&&&&&&&&&&&&&&&Point&&p1,p2;
&&&&&&&&&&&&&&&&double&&&&&&&&&&&&&&&&//&距离
&&&&&&&&};
&&&&&&&&//&组合类的构造函数
&&&&&&&&Distance::Distance(Point&a,&Point&b):p1(a),p2(b)
&&&&&&&&{
&&&&&&&&&&&&&&&&cout&&&&&Distance构造函数被调用&&&&&
&&&&&&&&&&&&&&&&double&x&=&double(p1.GetX()&-&p2.GetX());
&&&&&&&&&&&&&&&&double&y&=&double(p1.GetY()&-&p2.GetY());
&&&&&&&&&&&&&&&&dist&=&sqrt(x*x&+&y*y);
&&&&&&&&&&&&&&&&
&&&&&&&&}
&&&&&&&&int&_tmain(int&argc,&_TCHAR*&argv[])
&&&&&&&&{
&&&&&&&&&&&&&&&Point&myp1(1,1),&myp2(4,5);
&&&&&&&&&&&&&&&Distance&myd(myp1,&myp2);
&&&&&&&&&&&&&&&cout&&&&&The&distance&is:&;
&&&&&&&&&&&&&&&cout&&&&myd.GetDis()&&&&
&&&&&&&&&&&&&&&return&0;
&&&&&&&&}&&&&&& 这段程序的运行结果是:&&&&&& Point拷贝构造函数被调用&&&&&& Point拷贝构造函数被调用&&&&&& Point拷贝构造函数被调用&&&&&& Point拷贝构造函数被调用&&&&& &Distance构造函数被调用&&&&&& The distance is:5&&&&& &Point类的构造函数是内联成员函数,内联成员函数在中已经讲过。&&&&&& 鸡啄米给大家分析下这个程序,首先生成两个Point类的对象,然后构造Distance类的对象myd,最后输出两点的距离。Point类的拷贝构造函数被调用了4次,而且都是在Distance类构造函数执行之前进行的,在Distance构造函数进行实参和形参的结合时,也就是传入myp1和myp2的值时调用了两次,在用传入的值初始化内嵌对象p1和p2时又调用了两次。两点的距离在Distance的构造函数中计算出来,存放在其私有数据成员dist中,只能通过公有成员函数GetDis()来访问。&&&&& &鸡啄米再跟大家说下类组合时的一种特殊情况,就是两个类可能相互包含,即类A中有类B类型的内嵌对象,类B中也有A类型的内嵌对象。我们知道,C++中,要使用一个类必须在使用前已经声明了该类,但是两个类互相包含时就肯定有一个类在定义之前就被引用了,这时候怎么办呢?就要用到前向引用声明了。前向引用声明是在引用没有定义的类之前对该类进行声明,这只是为程序声明一个代表该类的标识符,类的具体定义可以在程序的其他地方,简单说,就是声明下这个标识符是个类,它的定义你可以在别的地方找到。&&&&& &比如,类A的公有成员函数f的形参是类B的对象,同时类B的公有成员函数g的形参是类A的对象,这时就必须使用前向引用声明:&&&&&&&class&B;&&//前向引用声明
&&&&&&&class&A
&&&&&&&{&&
&&&&&&&public:
&&&&&&&&&&&&&&&&&&&void&f(B&b);
&&&&&&&};
&&&&&&&class&B
&&&&&&&{&&
&&&&&&&public:
&&&&&&&&&&&&&&&&&&void&g(A&a);
&&&&&&&};&&&&& &这段程序的第一行给出了类B的前向引用声明,说明B是一个类,它具有类的所有属性,具体的定义在其他地方。&&&&&& 今天鸡啄米讲了类的组合,这个知识还是很实用的,可以让我们的程序更灵活,不至于太庞杂让人摸不着头脑。面向对象是不是很强大啊?希望大家从思想上领会它。
Javascript
Server脚本
Web Services当前位置:&>&&>&
类的组合和对象成员关系
&&& 类中的成员,除了基本的数据类型外,还可以是一个已定义的类的对象,称此做法为类的组合或类的聚合,这样的类简称为组合类。也就是说,类可以将其他类对象作为自己的成员,形成包含与被包含的关系。这样,定一类是,就可以利用已定义的类来构成新类,由若干结构简单、易于实现的类来构造复杂的类。这种方法,不仅简化了问题的描述,有利于软件开发效率的提高,也是软件复用的一种形式。
&&& 当一个类用另一个类的对象作为自己的成员时,称此对象为对象成员。声明对象成员时,其数据类型应为该对象成员所在类的类名。如:
&&& class A
&&&&& private:
&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //私有成员
&&&&& public:
&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //公有成员
&&& class B
&&&&& private:
&&&&&&&& A&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //对象成员
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //私有成员
&&&&& public:
&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //公有成员
正在载入评论数据中...C++基类和派生类的关系对基类和派生类的关系描述中,(
)是错误的。 A. 派生类是基类的具体化
B. 派生类是基类的子集C. 派生类是基类定义的延续 D. 派生类是基类的组合我的同学们选_百度作业帮
C++基类和派生类的关系对基类和派生类的关系描述中,(
)是错误的。 A. 派生类是基类的具体化
B. 派生类是基类的子集C. 派生类是基类定义的延续 D. 派生类是基类的组合我的同学们选
C++基类和派生类的关系对基类和派生类的关系描述中,(
)是错误的。 A. 派生类是基类的具体化
B. 派生类是基类的子集C. 派生类是基类定义的延续 D. 派生类是基类的组合我的同学们选了B可我觉得不对;但又不敢肯定也不知道应该选什么,所以请各位大虾指教,帮我选下答案。
应该是C,因为派生类是继承基类的同时可以添加扩展自己的成员!
应该B,比如D肯定是对的,那么派生类的范围更大..所以基类是派生类的子集....
B是错误的,派生类可以添加自己的成员函数,所以不是子集啦!C++设计类选择继承或组合
在C++程序设计设计类时,用到其他类的属性或者方法要明白是用组合还是继承。组合即是has a,该类拥有哪些属性或者方法;继承即是is a,该类拥有父类的属性或者方法。
&&& 这里举一个例子,假如有一个父类汽车,当有轿车、卡车、面包车等类似的实体时,此时应该选择继承,即派生类拥有父类汽车的属性或者方法;当有发动机、车门、车窗等和汽车相关的属性时,就应选择组合。
&& 总之,选择组合还是继承,就是要看是否需要新类向上映射。如果是的话,就选择继承,如果不需要,就应选择组合。
作者 Wentasy

我要回帖

更多关于 组合优化问题 的文章

 

随机推荐