欢迎来到论文网! 识人者智,自知者明,通过生日认识自己! 生日公历:
网站地图 | Tags标签 | RSS
论文网 论文网8200余万篇毕业论文、各种论文格式和论文范文以及9千多种期刊杂志的论文征稿及论文投稿信息,是论文写作、论文投稿和论文发表的论文参考网站,也是科研人员论文检测和发表论文的理想平台。lunwenf@yeah.net。
您当前的位置:首页 > 科技论文 > 计算机论文

C++中构造函数的使用

时间:2011-04-23  作者:秩名

论文导读:C++语言的一个重要机制是类的引入,它不仅丰富了C++的数据类型,而且增强了C++对现实世界的描述能力。在C++中,建立和初始化对象的过程由专门的成员函数来完成,这个函数很特殊,只要对象建立,它马上被调用,为对象分配空间和初始化,这个函数就是构造函数。类中数据成员可以分为两种:普通数据成员和对象成员,包含对象成员的类称为聚集类。由继承得到的类称为派生类,派生类中既包括从基类继承而来的成员(即基类子对象部分),又包括自身特有的成员(即新增成员部分)。
关键词:类,构造函数,聚集,派生
1.引言
C++语言的一个重要机制是类的引入,它不仅丰富了C++的数据类型,而且增强了C++对现实世界的描述能力。论文参考网。对象是类的一个实例,它描述的是现实世界中的实体,因此,一旦创建一个某类对象,就需要有一个有意义的初始值,表示该对象的初始状态。在C++中,建立和初始化对象的过程由专门的成员函数来完成,这个函数很特殊,只要对象建立,它马上被调用,为对象分配空间和初始化,这个函数就是构造函数。
2.普通构造函数
以类名作为函数名的函数称为类的构造函数(C++标准中认为构造函数是无名函数,原因是类型名不能作为函数名。为了便于理解和描述,将类名称为构造函数的函数名)。构造函数用于将其所属类的对象初始化到一个指定状态并且完成内存分配。其中,内存分配一般由编译器生成相关代码自动完成,而对象各个数据成员的初值状态则通过构造函数的函数体实现。
例1
#include <iostream.h>
class A
{public:
A(intx):{a=x;cout<<'A Constructing '<<a<<endl;} //有参构造函数
private:
int a;
};
void main()
{ A a1(1);
A *p1=new A(2);
}
运行结果如下:
A Constructing 1
A Constructing 2
不能为构造函数指定任何返回类型,即使void也不行;由于构造函数是无名函数,即对于程序正文而言是不可见的,因此,在程序中不能直接调用构造函数,它是由编译器自动调用的。例1的主函数中,首先调用有参构造函数创建了A类对象a1,然后,以操作符new带普通参数向堆区动态申请的方式初始化A类指针p1时,编译器自动调用的也是该类的有参构造函数,所以有上述两行输出结果。
3.默认构造函数
如果在例1的主函数中增加语句:A a2;,则程序编译时会出现一个语法错误,其原因是类A中只定义了一个有参构造函数,显然不能用它去构造无参对象a2,解决办法很简单,在类A的声明中增加一个无参构造函数如下:
A(){a=0;cout<<'DefaultConstructing '<<a<<endl;} //无参构造函数
此时,编译器会自动调用该无参构造函数去完成对象a2的初始化工作。类似地,若在主函数中增加语句:A *p2=new A;,则编译器也会自动调用该无参构造函数在堆区中创建一个无参匿名对象,然后用其地址去初始化A类指针p2。
由此可见,编译器自动调用构造函数的时机是在创建一个对象时:即以不带参数或带普通参数的方式执行一个对象定义语句或用操作符new动态创建对象时;构造函数可以带上形参,称为有参构造函数,并且可以带默认形参;也可以不带形参,称为无参构造函数,又叫默认构造函数或缺省构造函数,即构造函数可以重载。在创建对象时,编译器会根据所给实参的类型、个数与次序,选择恰当的构造函数完成对象的初始化工作;如果没有为一个类定义任何构造函数时,编译器会为该类自动生成一个隐含声明的默认构造函数,隐含声明的默认构造函数什么都不做。
4.转换构造函数
多态性是C++的三大基本特征(封装性,继承性,多态性)之一,C++的多态性包括强制多态、重载多态、包含多态和参数类型多态。将一种类型的值强制转换成为另一种类型的值称为类型强制,即强制多态。在基本数据类型之间可以通过显式的强制类型转换实现类型强制。论文参考网。如:对于int x;用x=(int)3.14;或x=int (3.14);或x=static_cast<int>(3.14);都可以将浮点数3.14转换为整型数3。在使用类类型时也同样存在类似的类型强制,只不过这种类型强制既可以通过显式的方式来完成,也可以隐式地由构造函数来自动转换,甚至可以根据需要在类中定义类型强制转换成员函数来完成指定的类型强制。
例2
#include <iostream.h>
class B {
public:
B(int x):b(x) {cout<<b<<' constructor is called! ';}
//构造函数用于类型强制
operatorint(){cout<<b<<' operator int() is called! '; return a;}
//类型转换成员函数用于类型强制
private:
int b;
};
void f(const B& x)
{
cout<<'functionf is called! ';
}
void main()
{
B obj(1);
f(2);//①
obj='a'; //②
int m=obj; //③
}
运行结果如下:
1 constructor is called!
2 constructor is called!
function f is called!
97 constructor is called!
97 operator int() is called!
例2运行后共有5行输出,其中,代码B obj(1);被编译时,系统将自动调用构造函数创建B类对象obj,形成结果中第1行输出;①处被编译时,由于在函数f中,形参是B类的引用,实参的类型与形参不一致,系统此时自动调用构造函数将常量2的类型int强制转换成为类类型B,具体过程是在main函数工作区中创建一个B类的匿名对象,并以常量2为初值初始化该匿名对象,然后函数f的形参x引用该匿名对象完成虚实结合,执行函数f的函数体,最后返回main函数,清除该匿名对象,形成结果中第2,3行输出;类似地,②处被编译时,系统也会自动调用构造函数完成由char类型向B类型的类型强制,形成结果中第4行输出;③处被编译时,在定义整型变量m并对其初始化时,初值是B类对象obj,因此系统将自动调用operator int()转换函数,将obj的类型由B强制转换成为int,然后再完成赋值操作,形成结果中第5行输出。
5.聚集类与派生类中的构造函数
类中数据成员可以分为两种:普通数据成员和对象成员,包含对象成员的类称为聚集类。显然,在聚集类的构造函数中,不仅要完成对普通成员的初始化工作,还要调用对象成员所属类的构造函数去完成对象成员的初始化。
继承是C++的又一大基本特征,通过继承可以有效的避免重复劳动,实现代码复用。由继承得到的类称为派生类,派生类中既包括从基类继承而来的成员(即基类子对象部分),又包括自身特有的成员(即新增成员部分)。由于构造函数不能被继承,所以在派生类的构造函数中,不仅要完成对新增成员的初始化工作,还要调用基类构造函数去完成基类子对象的初始化。
在聚集类和派生类中,构造函数执行的一般次序为:(1)按照被继承时的声明次序,依次调用基类构造函数完成各基类子对象的初始化;(2)按照在聚集类中声明的次序,依次调用对象成员所属类的构造函数完成各对象成员的初始化;(3)执行聚集类和派生类构造函数的函数体,完成自身普通数据成员的初始化。
例3
#include <iostream>
class A //基类A
{public:
A(int x): a(x){cout<<'AConstructing '<<a<<endl;}
protected:
int a;
};
class B //基类B
{public:
B(int x): b(x){cout<<'BConstructing '<<b<<endl;}
protected:
int b;
};
class C //对象成员所属类C
{public:
C(int x): c(x){cout<<'CConstructing '<<c<<endl;}
private:
int c;
};
class D //对象成员所属类D
{public:
D(int x): d(x){cout<<'DConstructing '<<d<<endl;}
private:
int d;
};
class E: public A, public B//聚集类、派生类E
{public:
E(int x1,int x2,intx3,int x4,int x5): objd(x4),objc(x3),B(x2),A(x1)
{e=x5;cout<<'EConstructing '<<e<<endl;}
private:
int e;
C objc; //对象成员
D objd; //对象成员
};
void main()
{ E e(1,2,3,4,5);
}
运行结果如下:
A Constructing 1
B Constructing 2
C Constructing 3
D Constructing 4
E Constructing 5
例3中共有5个类A、B、C、D、E,其中A、B作为E类的基类,C、D作为E类的对象成员所属类,E作为聚集类和派生类。派生类E的基类有A和B两个,是一种多继承关系,按照先A后B的声明次序进行继承,则在执行派生类E的构造函数时,首先按照继承时的声明次序(而不是派生类E的构造函数成员初始化列表中先B后A的次序),依次调用的是基类A和基类B的构造函数,来完成类E中两个基类子对象部分的初始化,形成结果中的前2行输出;其次,聚集类E中有两个对象成员objc和objd,分别属于类C和类D,按照声明时先objc后objd的次序(而不是聚集类E的构造函数成员初始化列表中先objd后objc的次序),依次调用类C和类D的构造函数,来完成类E中这两个对象成员的初始化,形成结果中的3,4两行输出;最后,类E中还有一个普通数据成员e,其初始化工作在自身类构造函数中完成,则最后执行的是类E自身构造函数的函数体,完成普通数据成员e的初始化,形成结果中的第5行输出。论文参考网。
6.结语
构造函数是类中的一种特殊的成员函数,是C++的一个难点。在C++程序中经常要用到类,而类中的数据成员不能在类声明时初始化,所以经常需要用构造函数来进行初始化,因此有必要弄清楚构造函数的分类,作用,调用次序等问题,以便更好地理解C++面向对象程序设计的实现机制。

参考文献:
[1] Bjarne Stroustrup. The C++Programming Language, Special Edition[M]. 北京:高等教育出版社, 2000
[2] 郑莉,刘慧宁,孟威. C++程序设计教程[M]. 北京: 清华大学出版社, 2001
[3] 吕凤翥. C++语言基础教程[M]. 北京: 清华大学出版社, 2004
 

查看相关论文专题
加入收藏  打印本文
上一篇论文:C#中数据传递方式的教学模型设计
下一篇论文:C语言程序设计题自动评分方法的研究与设计(图文)
科技论文分类
科技小论文 数学建模论文
数学论文 节能减排论文
数学小论文 低碳生活论文
物理论文 建筑工程论文
网站设计论文 农业论文
图书情报 环境保护论文
计算机论文 化学论文
机电一体化论文 生物论文
网络安全论文 机械论文
水利论文 地质论文
交通论文
相关计算机论文
最新计算机论文
读者推荐的计算机论文