C++默认构造函数

C++默认构造函数
C++默认构造函数

C++ 默认构造函数

1、每个类必须有一个构造函数,否则没法创建对象;

2、若programer没有提供任何构造函数,则C++提供一个默认的构造函数,该默认构造函数是无参构造函数,它仅负责创建对象,不做任何初始化的工作;

3、只要programer定义了一个构造函数(不管是无参还是有参构造),C++就不再提供默认的默认构造函数。即如果为类定义了一个带参的构造函数,还想要无参构造函数,就必须自己定义;

4、与变量定义类似,在用默认构造函数创建对象时,如果创建的是全局对象或静态对象,则对象的位模式全为0,否则,对象值是随机的。

注:2所述,C++在某些情况下会提供默认构造函数,但在某些情况下并不会自动调用。

实事上,当用户没有提供自定义的构造函数的时候,声明该类的对象,以及定义包含该对象的数组,都不会调用默认构造函数;但定义包含该对象的容器时,会自动调用默认的构造函数。

举例如下:

#include

#include

using std::cout;

using std::endl;

using std::vector;

class Student

{

public:

// Student() : val(6){} // 1

// Student(int val) : val(6){} // 2

int val;

};

void main()

{

Student s;

cout << s.val; // 编译通过,但运行时出错:the variable 's' is being used without being defined.

// 说明没有调用默认构造函数

Student arr[4];

cout << arr[2]; // 编译通过,但运行出错:the variable 'arr' is being used without being defined.

// 说明没有调用默认构造函数

vector< Student > vec(5);

cout << vec[3].val << endl; //运行无误,但输出结果未定义(取决于编译器,可能是随机值或0)

// 说明调用了默认构造函数

Student *ptr = new Student[4];

cout << ptr[1].val; //运行无误,但输出结果未定义(取决于编译器,可能是随机值或0) // 说明调用了默认构造函数

Student ss = Student(); // 显示调用

cout << ss.val; // 运行无误,但输出结果未定义(取决于编译器,可能是随机值或0)

// 说明调用了默认构造函数

}

若将Student定义体中的注释1去掉,即自定义无参构造函数,则main函数中的几种形式的对象定义都会调用该自定义的无参构造函数;

但只将注释2去掉,即自定义带参构造,而不提供无参构造,则main函数的几种形式的对象定义都将因为没有可用的默认构造函数而编译出错。

关于默认构造函数的几个错误认识

假期间闲来无事,就下载了某大师的VC++视频资料。在讲到C++时,说是如果程序员没有自己定义默认构造函数,那么编译器会自动为我们产生一个默认的构造函数(注:这是个错误的认识。编译器只在某些情况下提供默认构造函数)。本来这个错误的认识很多程序员都有,不足为奇。但有这么多年编程经验的高手也有这样的错误认识就不禁让我哑然了。

其实编程语言和我们所用的任何软件没有区别,例如Photoshop、AutoCAD之类。其唯一不同的是我们用的编程语言是基于编译器的,而应用软件是基于我们的编程语言的。

既然我们所用的软件是基于编译器的,那么理解编译器在背后到底为我们做了些什么、在什么情况下做了哪些事情就显得异常重要。这就像Photoshop会为你产生一些基本图形例如矩形、三角形之类,而不会凭空产生一些风景优美的图片一样。

在《C++ Annotated Reference Manual(ARM)[ELLIS90]》中的Section 12。1告诉我们:"Default constructors。。。在需要的时候被编译器产生出来"。

其实默认构造函数也是分为两类的:有用的、无用的。

所谓有用的标准,也就是默认构造函数会为我们的类做一些初始化操作。那么无用的就不会做任何工作,从而对我们的类也就没有任何意义。所以,我们通常所说的默认构造函数是指有用的默认构造函数,其英文名字叫nontrivial default constructor。

那么到底什么时候编译器会为我们产生nontrivial default constructor呢?有下面四中情况:

①如果一个类里面某个成员对象有nontrivial default constructor,编译器就会为我们的类产生

nontrivial default constructor。

那么编译器这样做的理由是什么?

答案是因为类成员对象有nontrivial default constructor,那么编译器就需要显式的来调用这个类成员对象的nontrivial default constructor。而编译器想显式的调用类成员对象的nontrivial default constructor,就需要自己来合成一些代码来调用。但是记住,编译器合成的nontrivial default constructor仅仅调用类成员对象的默认构造函数,而不对我们类里面的其它变量做任何初始化操作。

也就是说,如果你想初始化类成员变量以外的变量,例如一个int、一个String,那么必须自己定义默认构造函数来完成这些变量的初始化。而编译器会对你定义的默认构造函数做相应的扩展,从而调用类成员对象的nontrivial default constructor。

②如果一个派生类的基类有nontrivial default constructor,那么编译器会为派生类合成一个nontrivial default constructor。

编译器这样的理由是:因为派生类被合成时需要显式调用基类的默认构造函数。

③如何一个类里面隐式的含有任何virtual function table(或vtbl)、pointer member(或vptr)。

编译器这样做的理由很简单:因为这些vtbl或vptr需要编译器隐式(implicit)的合成出来,那么编译器就把合成动作放到了默认构造函数里面。所以编译器必须自己产生一个默认构造函数来完成这些操作。

所以如果你的类里带有任何virtual function,那么编译器会为你合成一个默认构造函数。

④如果一个类虚继承于其它类。

编译器这样做的理由和③类似:因为虚继承需要维护一个类似指针一样,可以动态的决定内存地址的东西(不同编译器对虚继承的实现不仅相同)。

那么除了以上四种情况,编译器并不会为我们的类产生默认构造函数。

所以编程中切忌想当然,要明白哪些事情是编译器做的,哪些事情需要程序员来完成的。就像堆所占用的资源需要程序员自己来释放,而栈空间是编译器管理的一样。

只有如此,才能编写出质量更高的代码。

C默认构造函数的作用

C#默认构造函数的作用 本文详细介绍C#默认构造函数的作用 构造函数主要用来初始化对象。它又分为静态(static)和实例(instance)构造函数两种类别。大家应该都了解如果来写类的构造函数,这里只说下默认构造函数的作用,以及在类中保留默认构造函数的重要性。实际上,我说错了。正确的说法是:以及在类中保留空参数构造函数的重要性。我们来写一个类A,代码如下: view plaincopy to clipboardprint? public class A { public int Number; //数字 public string Word; //文本 } //在Test类中实例化 public class Test { static void Main() { A a = new A(); //实例化,A()即为类A的默认构造函数 Console.WriteLine(“Number = {0}"nWord = {1}”,a.Number,a.Word); Console.read(); } } 输出的结果是: Number = 0 Word = ******************************* using System; class Point { public int x, y,z; public Point() { x = 0; y = 0; z = 0; } public Point(int x, int y,int z) { //把函数内容补充完整 this.x = x; this.y =y;

this.z =z; } public override string ToString() { return(String.Format("({0},{1},{2})", x, y,z)); } } class MainClass { static void Main() { Point p1 = new Point(); Point p2 = new Point(10,20,30); Console.WriteLine("三维中各点坐标:"); Console.WriteLine("点1的坐标为{0}", p1); Console.WriteLine("点2的坐标为{0}", p2); } } ******************************************************************************* ********* C#类的继承,构造函数实现及其调用顺序 类层层派生,在实例化的时候构造函数的调用顺序是怎样的? --从顶层基类开始向子类方向顺序调用无参构造. 默认构造(无参构造)和带参构造什么时候调用?--默认将从顶层父类的默认构造一直调用到当前类的默认构造. 下面是示例: /**//*--===------------------------------------------===--- 作者:许明会 日期:类的派生和构造函数间的关系,调用层次及实现 日期:2008年1月18日 17:30:43 若希望类能够有派生类,必须为其实现默认构造函数. 若类没有实现带参构造,编译器将自动创建默认构造函数. 若类实现了带参构造,则编译器不会自动生成默认构造. --===------------------------------------------===---*/ using System; namespace xumh { public class MyClass { public MyClass () {

C++拷贝构造函数(复制构造函数)

有的、已经存在的数据创建出一份新的数据,最终的结果是多了一份相同的数据。例如,将Word 文档拷贝到U盘去复印店打印,将D 盘的图片拷贝到桌面以方便浏览,将重要的文件上传到百度网盘以防止丢失等,都是「创建一份新数据」的意思。 在C++ 中,拷贝并没有脱离它本来的含义,只是将这个含义进行了“特化”,是指用已经存在的对象创建出一个新的对象。从本质上讲,对象也是一份数据,因为它会占用内存。 严格来说,对象的创建包括两个阶段,首先要分配内存空间,然后再进行初始化: ?分配内存很好理解,就是在堆区、栈区或者全局数据区留出足够多的字节。这个时候的内存还比较“原始”,没有被“教化”,它所包含的数据一般是零值或者随机值,没有实际的意义。 ?初始化就是首次对内存赋值,让它的数据有意义。注意是首次赋值,再次赋值不叫初始化。初始化的时候还可以为对象分配其他的资源(打开文件、连接网络、动态分配内存等),或者提前进行一些计算(根据价格和数量计算出总价、根据长度和宽度计算出矩形的面积等)等。说白了,初始化就是调用构造函数。 很明显,这里所说的拷贝是在初始化阶段进行的,也就是用其它对象的数据来初始化新对象的内存。

那么,如何用拷贝的方式来初始化一个对象呢?其实这样的例子比比皆是,string 类就是一个典型的例子。 1.#include 2.#include https://www.360docs.net/doc/885816273.html,ing namespace std; 4. 5.void func(string str){ 6.cout<

C++派生类的构造函数

前面我们说基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。 在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。 这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。 下面的例子展示了如何在派生类的构造函数中调用基类的构造函数: 1.#include https://www.360docs.net/doc/885816273.html,ing namespace std; 3. 4.//基类People 5.class People{ 6.protected: 7.char*m_name; 8.int m_age; 9.public: 10.People(char*,int); 11.}; 12.People::People(char*name,int age):m_name(name),m_age(age){} 13. 14.//派生类Student

15.class Student:public People{ 16.private: 17.float m_score; 18.public: 19.Student(char*name,int age,float score); 20.void display(); 21.}; 22.//People(name, age)就是调用基类的构造函数 23.Student::Student(char*name,int age,float score):People(name, age),m_score(score){} 24.void Student::display(){ 25.cout<

定义构造函数的四种方法

定义类的构造函数 作者:lyb661 时间:20150613 定义类的构造函数有如下几种方法: 1、使用默认构造函数(类不另行定义构造函数):能够创建一个类对象,但不能初始化类的各个成员。 2、显式定义带有参数的构造函数:在类方法中定义,使用多个参数初始化类的各个数据成员。 3、定义有默认值的构造函数:构造函数原型中为类的各个成员提供默认值。 4、使用构造函数初始化列表:这个构造函数初始化成员的方式显得更紧凑。 例如:有一个学生类。其中存储了学生的姓名、学号和分数。 class Student { private: std::string name; long number; double scores; public: Student(){}//1:default constructor Student(const std::string& na,long nu,double sc); Student(const std:;string& na="",long nu=0,double sc=0.0); Student(const std:;string& na="none",long nu=0,double sc=0.0):name(na),number(nu),scores(sc){} ……….. void display() const; //void set(std::string na,long nu,double sc); }; ......... Student::Student(const std::string& na,long nu,double sc) { name=na; number=nu; scores=sc; } void Student::display()const { std::cout<<"Name: "<

(完整版)拷贝构造函数

拷贝构造函数 一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。下面看一个类对象拷贝的简单例子。 #include using namespace std; class CExample { private: int a; public: //构造函数 CExample(int b) { a = b;} //一般函数 void Show () { cout< using namespace std;

private: int a; public: //构造函数 CExample(int b) { a = b;} //拷贝构造函数 CExample(const CExample& C) { a = C.a; } //一般函数 void Show () { cout<

C++继承与派生类习题

第九章继承与派生类 9.2 典型例题分析与解答 例题1:下列对派生类的描述中,()是错误的。 A.一个派生类可以作为另一个派生类的基类 B.派生类至少有一个基类 C.派生类的成员除了它自己的成员外,还包含了它的基类成员 D.派生类中继承的基类成员的访问权限到派生类保持不变 答案:D 分析:一个派生类可以作为另一个派生类的基类。无论是单继承还是多继承,派生类至少有 成 的成员时可能出现二义性。消除二义性的方法是采用作用域运算符。派生类和它的基类中出现同名函数时,不可能出现二义性。 例题4:多继承派生类构造函数构造对象时,()被最先调用。 A.派生类自己的构造函数 B.虚基类的构造函数 C.非虚基类的构造函数D.派生类中子对象类的构造函数 答案:B 分析:多继承派生类构造函数构造对象时,构造函数的调顺序是:虚基类的构造函数,派生类中子对象类的构造函数,派生类自己的构造函数。

例题5:C++类体系中,能被派生类继承的是()。 A.构造函数B.虚函数C.析构函数D.友元函数答案:B 分析:C++类体系中,构造函数、析构函数和友元函数是不能被派生类继承的. 例题6:设有基类定义: class Cbase { private: int a; protected: int b; public: int c; }; 用派生类中子对象类的析构函数,最后调用基类的析构函数。 例题11:设有以下类的定义: class A class B: protected A class C: private B { int A1; { int b1; { int c1; protected: int A2; protected: int b2; protected: int c2; public: int A3; public: int b3; public: int c3; }; }; }; 请按访问权限写出派生类C中具有的成员。 私有成员: (1)

拷贝构造函数

实验7拷贝构造函数 一、实验目的 (1) 掌握类的声明和对象的声明。 (2) 掌握拷贝构造函数的定义与使用 (3) 了解拷贝构造函数调用的时机 二、实验内容及步骤 1 新建c++源文件,找到week14文件夹中的copyStruDefine.cpp文件,复制到新建的源文件中运行,将运行结果记录下来,分析程序中执行哪条语句引起拷贝构造函数被调用的,将该语句的行号记录下来。 分析程序,第46 条语句Point pa(1,2) 执行时会调用构造函数,第47 条语句 Point pb=pa 执行时会调用拷贝构造函数。 2 程序中添加一个distance函数,用来计算2个点之间的距离。代码如下:

运行程序,记录运行结果。 分析程序,第52,53 条语句Point pa(7,4); Point pb(1,2); 执行时会调用构造函数,第46,47 条语句 double dx=a1.getX()-a2.getX();double dy=a1.getY()-a2.getY(); 执行时会调用拷贝构造函数。 3 设计一个函数mirror用来返回一个点在x轴的镜像坐标,如点A坐标为(1,2),它的镜像点A’坐标为(1,-2)。

分析:函数的结构分成2部分,函数头部和函数体 (1)函数的函数头部分语法格式:返回类型函数名(参数) 可以确定的是函数名mirror;这个函数会计算出一个点的镜像并返回,点的镜像还是一个点,因此可以确定函数的返回类型是void ;这个函数会将某个点的镜像计算出来,那到底计算的是那个点的镜像呢?这是不确定的,将不确定的因素定义为函数的参数,因此函数的参数类型是Point ;现将函数的第一行补充完整。 返回类型mirror(参数) (2)分析函数的函数体部分,即用”{ }”包围的部分。 我们通过参数传递接收到一个点的坐标,现在要计算另一个点的坐标(镜像点),因此需要在函数体内定义另外一个点类型的对象来存放镜像点的坐标。将镜像点的x坐标赋值为参数点的x坐标值,将镜像点的y坐标赋值为参数点的y坐标值的负数值(需要注意Point类中的x和y成员都是私有的)。将镜像点坐标赋值完成后,用return语句将镜像点返回。 (3)在主函数中测试mirror函数。 #include #include using namespace std; /* 类的函数成员-->构造函数(创建对象并赋初值) int a=10; int b=a;//创建变量b并赋初值,这个初值放在a中 创建对象(新)时,构造函数的参数是对象(已存在) --拷贝构造函数 */ class Point{ private: double x;

派生类

继承与派生类 1 知识要点 1.掌握继承和派生的定义,派生类的定义方法。 (1)掌握继承的两种类型:单继承和多继承。 (2)掌握private,public,protected三种继承方式的特点。继承方式决定了基类中的成员在派生类中的属性。三种继承方式的共同点:基类的private成员在 派生类中不可见。区别:对于私有继承,基类的public、protected成员在派 生类中作为private成员;对于公有继承,基类的public、protected成员在派 生类中访问属性不变;对于保护继承,基类的public、protected成员在派生 类中作为protected成员。 (3)掌握派生类中的构造函数和析构函数的使用。基类的构造函数和析构函数不能继承,所以必要时在派生类中定义自己的构造函数和析构函数。派生列的 构造函数完成基类中新增数据成员和基类数据成员的初始化,基类数据成员 的初始化通过基类构造函数来实现。 (4)掌握派生类的同名覆盖规则。 (5)掌握赋值兼容规则。基类对象可以使用公有派生类对象来代替,包括:派生类对象可以赋值给基类对象;派生类对象可以初始化基类对象的引用;基类 类型指针可以指向派生类对象。 2.掌握多重继承的概念、定义方法、多重继承派生类构造函数的执行顺序。派生类构造函数的执行顺序是先执行所有基类的构造函数(顺序按照定义派生类时指定的各基类顺序),在执行对象成员所在类的构造函数(顺序按照他们在类中的声明顺序),最后执行派生类构造函数体中的内容。 3.掌握虚基类的概念和定义方法。在多重继承中,如果多条继承路径上有一个公共的基类,则在这些路径的汇合点上的派生类会产生来自不同路径的公共基类的多个拷贝,如果用virtual把公共基类定义成虚基类,则只会保留公共基类的一个拷贝。 2 典型例题分析与解答 例题1:下列对派生类的描述中,()是错误的。 A.一个派生类可以作为另一个派生类的基类 B.派生类至少有一个基类 C.派生类的成员除了它自己的成员外,还包含了它的基类成员 D.派生类中继承的基类成员的访问权限到派生类保持不变 答案:D 分析:一个派生类可以作为另一个派生类的基类。无论是单继承还是多继承,派生类至少有一个基类。派生类的成员除了它自己的成员外,还包含了它的基类成员。派生类中继承的基类成员的访问权限到派生类受继承方式影响的,对于私有继承,基类的public,protected成员在派生类中作为private成员;对于公有继承,基类的public,protected成员在派生类中访问属性不变;对于保护继承,基类的public、protected成员在派生类中作为protected成员。

java中什么是构造函数

java中类的构造函数到底有什么用 如题,例如一段代码 class point2{ int x,y; point2(int a,int b){//构造函数;含参的构造函数;构造方法必须要和类名一致 //且没有返回值 x=a; y=b; } void output(){ System.out.println(x); System.out.println(y); } public static void main(String args[]){//类的实例 point2 pt; pt=new point2(3,3);//声明实例变量;传递参数给构造函数的变量 pt.output();//实际上调用了类中的构造函数; } } 那么我不用构造函数,只声明成员变量是否可以直接代替构造函数,请详细解释构造函数的作用 满意回答 什么是构造函数,问的好。 开始的时候我也不理解为什么要构造函数。因为那时候的设计思想还停留在面向过程编程。即我要干什么事,这件事有几个步骤,然后我决定怎么干。 面向对象不是这么直接简单,它的设计思想就是要代码重用。即我以前干过类似的事,那么我找出以前可以用到的代码,完成一部分。以前没有的我重新写。这样就有了类。 回到你提的问题。有了类,就是有了可以重用的代码,但是我怎么产生这个对象呢。必须要实例化这个类(当然这不是唯一产生对象的途径,比如单例模式,但本质上说所有途径都是一样的)。那么就要用到构造函数。即告诉程序我现在要实例化一个对象了,你给我马上分配内存。将内存的首地址赋给我指定的类对象。而且有时候你需要传递参数到函数里面,有了构造函数就方便了,构造函数

可以有无数个。当然,传递参数到到对象里面也可以其它方法,比如直接赋一个值给成员变量,举例: class point2{ int x,y; point2(){ } point2(int a,int b){//构造函数;含参的构造函数;构造方法必须要和类名一致 //且没有返回值 x=a; y=b; } void output(){ System.out.println(x); System.out.println(y); } public static void main(String args[]){ point2 pt=new point2();//实例化对象,这时候x,y没有赋值,默认初始值为0; pt.output(); pt.x=3;pt.y=3; pt.output(); } } =============================================================================== ===============================================================================

构造函数

c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初学者有所帮助。 c++类的构造函数详解 一、构造函数是干什么的 class Counter { public: // 类Counter的构造函数 // 特点:以类名作为函数名,无返回类型 Counter() { m_value = 0; } private: // 数据成员 int m_value; } 该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数->由构造函数完成成员的初始化工作 eg: Counter c1; 编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调用构造函数Counter( )自动地初始化对象c1的m_value值设置为0 故: 构造函数的作用:初始化对象的数据成员。 二、构造函数的种类 class Complex { private : double m_real; double m_imag;

public: // 无参数构造函数 // 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做 // 只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来 Complex(void) { m_real = 0.0; m_imag = 0.0; } // 一般构造函数(也称重载构造函数) // 一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理) // 例如:你还可以写一个Complex( int num)的构造函数出来 // 创建对象时根据传入的参数不同调用不同的构造函数 Complex(double real, double imag) { m_real = real; m_imag = imag; } // 复制构造函数(也称为拷贝构造函数) // 复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中// 若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询有关“浅拷贝”、“深拷贝”的文章论述 Complex(const Complex & c) { // 将对象c中的数据成员值复制过来 m_real = c.m_real; m_img = c.m_img; } // 类型转换构造函数,根据一个指定的类型的对象创建一个本类的对象 // 例如:下面将根据一个double类型的对象创建了一个Complex对象 Complex::Complex(double r) { m_real = r; m_imag = 0.0;

【重要】C++拷贝函数详解 20150111

C++拷贝函数详解 1.什么是拷贝构造函数: CA(const CA& C)就是我们自定义的拷贝构造函数。可见,拷贝构造函数是一种特殊的构 造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参 数是const类型,不可变的。例如:类X的拷贝构造函数的形式为X(X& x)。 当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷 贝构造函数就会被自动调用。 也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数: ①程序中需要新建立一个对象,并用另一个同类的对象对它初始化,如前面介绍的那样。 ②当函数的参数为类的对象时。 在调用函数时需要将实参对象完整地传递给形参,也就是需要建立一个实参的拷贝,这就 是按实参复制一个形参,系统是通过调用复制构造函数来实现的,这样能保证形参具有和实参 完全相同的值。 ③函数的返回值是类的对象。 在函数调用完毕将返回值带回函数调用处时。 此时需要将函数中的对象复制一个临时对象并传给该函数的调用处。如 Box f( ) //函数f的类型为Box类类型 {Box box1(12,15,18); return box1; //返回值是Box类的对象 } int main( ) {Box box2; //定义Box类的对象box2 box2=f( ); //调用f函数,返回Box类的临时对象,并将它赋值给 box2 } 如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的 拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,后面将进行说明。 自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。 浅拷贝和深拷贝 在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的

c++派生类与继承实验报告

实验2 派生类与继承 实验课程名:面向对象程序设计(C++) 专业班级:学号:姓名: 实验时间:实验地点:指导教师: 2.1实验目的和要求 (1) 掌握派生类的声明方法和派生类构造函数的定义方法。 (2) 掌握不同继承方式下,基类成员在派生类中的访问属性。 (3) 掌握在继承方式下,构造函数与析构函数的执行顺序与构造规则。 (4) 学习虚基类在解决二义性问题中的作用。

二、实验内容 一、构造一个类Geometry 及其派生类,该类主要实现关于几何图形的基本操作。对于基类“几何图形”,有求面积、求体积的函数(纯虚函数),其派生类圆和矩形主要有初始化(构造函数),求面积,求周长操作,类圆的派生类圆球和圆柱有求表面积、体积操作。 试在主函数中分别定义圆、圆球、圆柱以及矩形的对象,并调用其成员函数实现其相应操作。 实验代码如下: #include using namespace std; class Geometry { public: Geometry(){} Circle radiums Circle() ~Circle() Ball Ball() ~Ball() Geometry Geometry() ~Geometry() GetArea() GetPerimeter() Getcolume() show() Column Column() ~Column() Rectangle Rectangle() ~Rectangle()

~Geometry(){} double GetArea(){}//求面积函数double GetPerimeter(){}//求体积函数double Getcolume(){}//求周长函数 virtual show(){} }; class Circle:public Geometry { public: Circle(double i) { radiums=i; } ~Circle(){} double GetArea(); double Getcolume(); double R() { return radiums; } show(); private:

c 类构造函数详解

这篇文章主要介绍了c++类构造函数示例,需要的朋友可以参考下 代码如下: //一、构造函数是干什么的 /* 类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数->由构造函数完成成员的初始化工作 eg: Counter c1; 编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调用构造函数Counter( )自动地初始化对象,初始化之后c1的m_value值设置为0 故:构造函数的作用:初始化对象的数据成员。*/ class Counter { public: // 类Counter的构造函数,以类名作为函数名,无返回类型 Counter(){ m_value = 0; } private: int m_value; // 类私有的数据成员 } //二、构造函数的种类 #include using namespace std; class Complex { private : double m_real; double m_imag; public: //*无参数构造函数 // 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做 // 只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来Complex(void) { m_real = 0.0; m_imag = 0.0; } //*一般构造函数(也称重载构造函数) //一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理) //例如:你还可以写一个Complex(int num)的构造函数出来,创建对象时根据传入的参数不同调用不同的构造函数 Complex(double real, double imag)

Java默认构造函数的作用

class Person { private String name=""; private int age=0; public Person() { System.out.println("person无参数构造函数"); } public Person(String name,int age) { https://www.360docs.net/doc/885816273.html,=name; this.age=age; System.out.println("person 2 参数的构造函数"); } } class Student extends Person { private String school; private String grade; public Student() { System.out.println("student 无参数的构造函数"); } public Student(String name ,int age,String school) { System.out.println("student 3 参数的构造函数"); } public Student(String name ,int age,String school,String grade) { super(name,age); this.school=school;

this.grade=grade; System.out.println("student 4 参数的构造函数,super()."); } } class Test { public static void main(String [] args) { System.out.println("st1:"); Student st2=new Student(); System.out.println("---------------------------"); System.out.println("st2:"); Student st=new Student("zhangshan",76,"武大"); System.out.println("---------------------------"); System.out.println("st3:"); Student st3=new Student("lisi",24,"武大","研究生"); } } /* ======================================= 输出如下: E:JavaWork>java Test st1: person无参数构造函数 student 无参数的构造函数 --------------------------- st2: person无参数构造函数 student 3 参数的构造函数 --------------------------- st3:

构造函数初始化成员变量

请问在构造函数中使用初始化清单和直接在构造函数内初始化成员变量有什么区别? 比如: construct_function():var1(1),var2(2),var(3) {} 和 construct_function() { var1 = 1; var2 = 2; var3 = 3; } 有没有什么本质区别? =============================================================================== ======= construct_function():var1(1),var2(2),var(3) {} 初始化 construct_function() { var1 = 1; var2 = 2; var3 = 3; }赋值 首先把数据成员按类型分类 1、内置数据类型,复合类型(指针,引用) 2、用户定义类型(类类型) 分情况说明: 对于类型1,在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的。要是const类型的话只能使用初始化列表。 对于类型2,结果上相同,但是性能上存在很大的差别。 因为类类型的数据成员对象在进入函数体是已经构造完成,也就是说在成员初始化列表处进行构造对象的工作,这是调用一个构造函数,在进入函数体之后,进行的是对已经构造好的类对象赋值,又调用其拷贝赋值操作符才能完成(如果并未提供,则使用编译器提供的默认按成员赋值行为)。 举个例说明 class A; class B {

public: B(){a = 3;} private: A a; } class A { public: A(){} A(int){value = 3;} int value; } 像上面,我们使a对象的value为3,调用一个A的构造函数+一个默认拷贝赋值符,才达到目的。B::B():a(3){} 像这样,只调用了一个构造函数就得到了所需的对象啦,所以性能好。 注意:对于const成员,无缺省构造函数的类对象成员,均需放在成员初始化列表。 再举个例子: class A { public: A(int i){} }; class B { public: B() : ci(3), a(3){} private: const int ci; A a; }; int main() { B b; return 0; } 对于const成员,无缺省构造函数的类对象成员,均需放在成员初始化列表。

拷贝构造函数&默认拷贝构造函数&拷贝构造函数调用几种情况

一、拷贝构造函数 如果类中没有说明拷贝构造函数,则系统自动生成一个缺省复制构造函数,作为该类的公有成员 也可以进行自定义拷贝构造函数 自定义拷贝构造函数的例子: Test::Test(const Test& other) : num_(other.num_) { //num_ = other.num_; cout<<"Initializing with other "<

验证类中有无该构造函数

第一题验证类中有无该构造函数,如果没有是如何运行的? (1)类中不存在该构造函数。 (2)创建对象不带参数时调用空参构造函数。带参数时调用带相应参数列表的构造函数。 #include #include #include "43.h" using namespace std; int main() { String s1="asdf"; s1.PutString(); return 0; } 第二题赋值运算符是如何提供支持和拷贝构造函数有什么区别? 相等时,返回该数据。不相等时,删除当前对象中的字符串,然后开辟新空间把参数存入,返回当前对象。 拷贝构造函数要先读取做为参数的对象中字符串的长度,而赋值运算符要先删除当前对象中的字符串。 需要定义析构函数,意思就是说类里面有需要手动释放的资源,比如指针那么如果用了默认拷贝构造,指针赋值时,会把两个指针指向同一块内存地址,那么删除一个对象时,另一个指针具有不确定性。 当类成员变量存在动态分配的指针,就需要建立拷贝构造函数和赋值运算符重载。 有如下代码: #include using namespace std; class string { public: int i; string(){cout << "a" << endl;} string(const char *rhs){cout << "b" << endl;} //拷贝构造函数 ~string){cout << "c" << endl;} };

void test(const char *rhs) { } int main() { return 0; } 如果代码如下如下 string test1; string test2 = test1;//调用test1的拷贝构造函数初始化对象test2 ****************************************** 如果代码如下: string test1,teast2; string test2 = test1; 不会调用string的拷贝构造函数,因为test2已经被初始化过了,此时如果想要正确对test2赋值,需要重载运算符= Const sting& operator=(const char *rhs) { return *this; } 第三题下标运算符是不是重载?判断依据? (1)是重载 (2)如果没有重载,则主函数中“s1[4]”应该写为“s1.itsString[4]”。 当到输出语句中的s1[4]时,调用带const限定的函数。 当到s1[4]='x'时,调用返回类型为char &的函数。

相关文档
最新文档