当前位置:文档之家› C++派生类的构造函数

C++派生类的构造函数

C++派生类的构造函数
C++派生类的构造函数

前面我们说基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。

在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。

这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。

下面的例子展示了如何在派生类的构造函数中调用基类的构造函数:

1.#include

https://www.doczj.com/doc/096477924.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<

26.}

27.

28.int main(){

29.Student stu("小明",16,90.5);

30.stu.display();

31.

32.return0;

33.}

运行结果为:

小明的年龄是16,成绩是90.5。

请注意第23 行代码:

1.Student::Student(char*name,int age,float score):People(name, age),m_score(score){}

也可以将基类构造函数的调用放在参数初始化表后面:

1.Student::Student(char*name,int age,float score):m_score(score),People(name, age){}

但是不管它们的顺序如何,派生类构造函数总是先调用基类构造函数再执行其他代码(包括参数初始化表以及函数体中的代码),总体上看和下面的形式类似:

1.Student::Student(char*name,int age,float score){

2.People(name, age);

3.m_score = score;

4.}

当然这段代码只是为了方便大家理解,实际上这样写是错误的,因为基类构造函数不会被继承,不能当做普通的成员函数来调用。换句话说,只能将基类构造函数的调用放在函数头部,不能放在函数体中。

另外,函数头部是对基类构造函数的调用,而不是声明,所以括号里的参数是实参,它们不但可以是派生类构造函数参数列表中的参数,还可以是局部变量、常量等,例如:

1.Student::Student(char*name,int age,float score):People("小明",16),m_score(score){}

构造函数的调用顺序

从上面的分析中可以看出,基类构造函数总是被优先调用,这说明创建派生类对象时,会先调用基类构造函数,再调用派生类构造函数,如果继承关系有好几层的话,例如:

那么创建C 类对象时构造函数的执行顺序为:

构造函数的调用顺序是按照继承的层次自顶向下、从基类再到派生类的。

还有一点要注意,派生类构造函数中只能调用直接基类的构造函数,不能调用间接基类的。

以上面的A、B、C 类为例,C 是最终的派生类,B 就是C 的直接基类,A 就是C 的间接基类。

C++ 这样规定是有道理的,因为我们在C 中调用了B 的构造函数,B 又调用了A 的构造函数,相当于C 间接地(或者说隐式地)调用了A 的构造函数,如果再在C 中显式地调用A 的构造函数,那么A 的构造函数就被调用了两次,相应地,初始化工作也做了两次,这不仅是多余的,还会浪费CPU时间以及内存,毫无益处,所以C++ 禁止在C 中显式地调用A 的构造函数。

基类构造函数调用规则

事实上,通过派生类创建对象时必须要调用基类的构造函数,这是语法规定。换句话说,定义派生类构造函数时最好指明基类构造函数;如果不指明,就调用基类的默认构造函数(不带参数的构造函数);如果没有默认构造函数,那么编译失败。请看下面的例子:

1.#include

https://www.doczj.com/doc/096477924.html,ing namespace std;

3.

4.//基类People

5.class People{

6.public:

7.People();//基类默认构造函数

8.People(char*name,int age);

9.protected:

10.char*m_name;

11.int m_age;

12.};

13.People::People():m_name("xxx"),m_age(0){}

14.People::People(char*name,int age):m_name(name),m_age(age){}

15.

16.//派生类Student

17.class Student:public People{

18.public:

19.Student();

20.Student(char*,int,float);

21.public:

22.void display();

23.private:

24.float m_score;

25.};

26.Student::Student():m_score(0.0){}//派生类默认构造函数

27.Student::Student(char*name,int age,float score):People(name, age),m_score(score){}

28.void Student::display(){

29.cout<

30.}

31.

32.int main(){

33.Student stu1;

34.stu1.display();

35.

36.Student stu2("小明",16,90.5);

37.stu2.display();

38.

39.return0;

40.}

运行结果:

xxx的年龄是0,成绩是0。

小明的年龄是16,成绩是90.5。

类的哪一个构造函数,从运行结果可以很明显地看出来,系统默认调用了不带参数的构造函

的输出结果将变为:

xxx的年龄是0,成绩是90.5。

如果将基类People 中不带参数的构造函数删除,那么会发生编译错误,因为创建对象stu1 时需要调用People 类的默认构造函数,而People 类中已经显式定义了构造函数,编译器不会再生成默认的构造函数。

C++派生类的构造函数

前面我们说基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。 在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。 这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。 下面的例子展示了如何在派生类的构造函数中调用基类的构造函数: 1.#include https://www.doczj.com/doc/096477924.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<

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 () {

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++继承与派生类习题

第九章继承与派生类 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)

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)

派生类

继承与派生类 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成员。

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:

Java默认构造函数的作用

class Person { private String name=""; private int age=0; public Person() { System.out.println("person无参数构造函数"); } public Person(String name,int age) { https://www.doczj.com/doc/096477924.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:

课题: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)的构造函数出来 // 创建对象时根据传入的参数不同调用不同的构造函数

构造函数解题的三个类型

构造函数解题的三个类型 构造函数解题是近几年高考命题的热点,笔者研究近年的高考题,发现构造函数解题主要有以下三种类型,下面举例说明. 类型1.整体构造一个函数,这是最常见的构造方法,高考题中利用这个方法的题型最为多见. 例1 解不等式:3381050(1)1 x x x x +-->++. 解:原不等式即3322()5()511 x x x x +>+++, 令3()5f x x x =+,则2()350f x x '=+>, ∴3()5f x x x =+在R 上是增函数, ∴原不等式即21 x x >+, ∴解得 2x <-,或11x -<<, ∴原不等式的解集为{|2x x <-,或11}x -<<. 类型2.构造两个函数,这种类型的题目较少,技巧较强 例2 若20()2()||f x x x m x m x =+---≥对于一切[1,2]x ∈恒成立,求实数m 的取值范围. 解:令()()||g x x m x m =--,2()2h x x x =-,则()()()f x g x h x =+. ∵22,(),()()||(),,m x m x g x x m x m x m x m ?-=--=?--, ∴()h x 在[1,2]x ∈上是增函数. ∴()()()f x g x h x =+在[1,2]x ∈上是增函数, ∴min ()(1)1(1)|1|f x f m m ==+--. 由题意只要01(1)|1|m m +--≥, ∴2101(1)m m ??--?≥≥或2101(1)m m

验证类中有无该构造函数

第一题验证类中有无该构造函数,如果没有是如何运行的? (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 &的函数。

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_imag = c.m_imag; } // 类型转换构造函数,根据一个指定的类型的对象创建一个本类的对象, //需要注意的一点是,这个其实就是一般的构造函数,但是对于出现这种单参数的构造函数,C++会默认将参数对应的类型转换为该类类型,有时候这种隐私的转换是我们所不想要的,所以需要使用explicit来限制这种转换。 // 例如:下面将根据一个double类型的对象创建了一个Complex对象 Complex(double r) { m_real = r; m_imag = 0.0; } // 等号运算符重载(也叫赋值构造函数) // 注意,这个类似复制构造函数,将=右边的本类对象的值复制给等号左边的对象,它不属于构造函数,等号左右两边的对象必须已经被创建 // 若没有显示的写=运算符重载,则系统也会创建一个默认的=运算符重载,只做一些基本的拷贝工作 Complex &operator=( const Complex &rhs ) { // 首先检测等号右边的是否就是左边的对象本身,若是本对象本身,则直接返回 if ( this == &rhs ) { return *this; } // 复制等号右边的成员到左边的对象中 this->m_real = rhs.m_real;

派生类构造函数

派生类构造函数 派生类的数据成员由所有基类的数据成员与派生类新增的数据成员共同组成,如果派生类新增成员中包括其他类的对象(子对象),派生类的数据成员中实际上还间接包括了这些对象的数据成员。因此,构造派生类的对象时,必须对基类数据成员、新增数据成员和成员对象的数据成员进行初始化。派生类的构造函数必须要以合适的初值作为参数,隐含调用基类和新增对象成员的构造函数,来初始化它们各自的数据成员,然后再加入新的语句对新增普通数据成员进行初始化。 派生类构造函数的一般格式如下: <派生类名>::<派生类名>(<参数表>) : <基类名1>(<参数表1>), ……, <基类名n>(<参数表n>), <子对象名1>(<参数表n+1>), ……, <子对象名m>(<参数表n+m>) { <派生类构造函数体> //派生类新增成员的初始化 } 说明: (1) 对基类成员和子对象成员的初始化必须在成员初始化列表中进行,新增成员的初始化既可以在成员初始化列表中进行,也可以在构造函数体中进行。 (2) 派生类构造函数必须对这三类成员进行初始化,其执行顺序如下所述。 . 调用基类构造函数; . 调用子对象的构造函数; . 派生类的构造函数体; (3) 当派生类有多个基类时,处于同一层次的各个基类的构造函数的调用顺序取决于定义派生类时声明的顺序(自左向右),而与在派生类构造函数的成员初始化列表中给出的顺序无关。 (4) 如果派生类的基类也是一个派生类,则每个派生类只需负责其直接基类的构造,依次上溯。 (5) 当派生类中有多个子对象时,各个子对象构造函数的调用顺序也取决于在派生类中定义的顺序(自前至后),而与在派生类构造函数的成员初始化列表中给出的顺序无关。 (6) 派生类构造函数提供了将参数传递给基类构造函数的途径,以保证在基类进行初始化时能够获得必要的数据。因此,如果基类的构造函数定义了一个或多个参数时,派生类必须定义构造函数。 (7) 如果基类中定义了缺省构造函数或根本没有定义任何一个构造函数(此时,由编译器自动生成缺省构造函数)时,在派生类构造函数的定义中可以省略对基类构造函数的调用,即省略"<基类名>(<参数表>)"。 (8) 子对象的情况与基类相同。 (9) 当所有的基类和子对象的构造函数都可以省略时,可以省略派生类构造函数的成员初始化列表。

构造方法

Java构造方法 一、构造方法及其作用 new一个对象的时候要用到构造函数,例如Hello hello = new Hello();这时调用的是Hello的无参数构造方法;Hello hello = new Hello("hi");这个是调用Hello有参数构造方法,如果Hello类中已经有了一个有参数的构造方法,这时再使用Hello hello = new Hello();来创建对象的时候就会出错,这就是为什么强调写了有参数的构造方法就最好加一个无参数的构造方法. 特点: 1、构造方法名一定与类同名 2、构造方法无返回值类型(void 也不行),不能被static、final、synchronized、abstract、native等修饰。因为构造方法用于初始化一个新建的对象,所以用static修饰没有意义。多个线程不会同时创建内存地址相同的同一个对象,因此用synchronized修饰没有必要。 3、构造方法可以没有(默认一个无参构造方法),也可以有多个构造方法,他们之间构成重载关系,表达对象的多种初始化行为 4、如果定义有参构造函数,则无参构造函数将被自动屏蔽 5、构造方法不能被继承,但子类可以通过super调用父类的构造方法 6、构造方法不能手动调用,在创建类实例的时候自动调用构造方法 作用: 在多数情况下,初始化一个对象的最终步骤是去调用这个对象的构造方法。构造方法负责对象的初始化工作,为实例变量赋予合适的初始值。 二、默认构造方法 在JAVA中如果不写构造方法的话,会默认加上一个无参数的构造方法,但是如果已经有了一个有参数的构造方法,那么无参数的构造方法就不会默认被加上。此时创建无参数对象时,报错。 publicclass Sample1 { } publicclass Sample2 { public Sample2(int a) { System.out.println("My Constructor");

类的构造函数和析构函数

C++面向对象编程入门:构造函数与析构函数 请注意,这一节内容是c++的重点,要特别注意! 我们先说一下什么是构造函数。 上一个教程我们简单说了关于类的一些基本内容,对于类对象成员的初始化我们始终是建立成员函数然后手工调用该函数对成员进行赋值的,那么在c++中对于类来说有没有更方便的方式能够在对象创建的时候就自动初始化成员变量呢,这一点对操作保护成员是至关重要的,答案是肯定的。关于c++类成员的初始化,有专门的构造函数来进行自动操作而无需要手工调用,在正式讲解之前先看看c++对构造函数的一个基本定义。 1.C++规定,每个类必须有默认的构造函数,没有构造函数就不能创建对象。 2.若没有提供任何构造函数,那么c++提供自动提供一个默认的构造函数,该默认构造函数是一个没有参数的构造函数,它仅仅负责创建对象而不做任何赋值操作。 3.只要类中提供了任意一个构造函数,那么c++就不在自动提供默认构造函数。 4.类对象的定义和变量的定义类似,使用默认构造函数创建对象的时候,如果创建的是静态或者是全局对象,则对象的位模式全部为0,否则将会是随即的。 我们来看下面的代码: #include using namespace std; class Student { public: Student()//无参数构造函数 { number = 1; score = 100; } void show(); protected: int number; int score; }; void Student::show() { cout<

构造函数的总结

概述: 构造函数是在实例化对象时自动调用的函数。它们必须与所属的类同名,且不能有返回值。类或结构可能有多个接受不同参数的构造函数。构造函数使得我们可设置默认值、限制实例化以及编写灵活且便于阅读的代码。 如果您没有为对象提供构造函数,则默认情况下 C# 将创建一个构造函数,该构造函数实例化对象,并将成员变量设置为 Default Values Table (C# Reference)中列出的默认值。静态类和结构也可以有构造函数。 本文目的: 介绍构造函数、静态构造函数、在构造函数中调用其他构造函数以及构造函数在派生类中的应用。 正文: 1 单个类的构造函数 1.1 无参构造函数 public class UserAccessor { ///

///无参构造函数 /// public UserAccessor() { } } 上面就是一个最简单的构造函数,可以看出该构造函数满足概述中所述的构造函数条件,在实例化UserAccessor类时,就执行UserAccessor()方法中的代码,在这里我们可以写下自定义的代码,如给字段赋值等。 1.2 有参构造函数

public class UserModel { private string_userID; ///

///有参构造函数 /// /// public UserModel(string userID) { _userID = userID; } } 在实例化UserModel类时,我们就需要使用UserModel userModel = new UserModel("userIdDemo");实例化时必须传入制定的参数,这样就可以在实例化时存储于该实例相关的数据。 1.3 默认构造函数 如非必要我们可以不向一个类提供构造函数,编译器会在后台创建一个默认的构造函数。但如果提供了自定义的构造函数,编译器就不会提供默认的构造函数。 1.4 构造函数的重载 构造函数的重载和普通的函数重载遵循相同的规则,可以为函数提供任意多的构造函数重载,只要它们满足重载的条件即可。 1.5 构造函数的修饰符

C类构造函数初始化列表

类构造函数初始化列表 初始化列表地定义在使用编程地过程当中,常常需要对类成员进行初始化,通常地方法有两种:一种是构造函数内对类地成员赋值,一种则是使用初始化列表地构造函数显式地初始化类地成员. 构造函数初始化列表以一个冒号开始,接着是以逗号分隔地数据成员列表,每个数据成员后面跟一个放在括号中地初始化式.例如:{ : ; ; 构造函数初始化列表(): ()() {} 构造函数内部赋值() { ; ; } }; 从技术上说,用初始化列表来初始化类成员比较好,但是在大多数情况下,两者实际上没有什么区别.第二种语法被称为成员初始化列表,之所以要使用这种语法有两个原因:一个原因是必须这么做,另一个原因是出于效率考虑初始化列表地必要性初始化和赋值对内置类型地成员没有什么大地区别,像上面地任一个构造函数都可以.但在一些情况下,初始化列表可以做到构造函数做不到地事情: 、类里面有类型地成员,它是不能被赋值地,所以需要在初始化列表里面初始化它; 、引用类型地成员(也就是名字成员,它作为一个现有名字地别名),也是需要在初始化列表里面初始化地,目地是为了生成了一个其名字成员在类外可以被修改而在内部是只读地对象;

、需要调用基类地构造函数,且此基类构造函数是有参数地; 、类里面有其他类类型地成员,且这个“其他类”地构造函数是有参数地. 举个例子:设想你有一个类成员,它本身是一个类或者结构,而且只有一个带一个参数地构造函数. { : ( ) { ... } }; 因为有一个显式声明地构造函数,编译器不产生一个缺省构造函数(不带参数),所以没有一个整数就无法创建地一个实例. * ; 出错!! * (); 如果是另一个类地成员,你怎样初始化它呢?答案是你必须使用成员初始化列表. { ; : (); }; 必须使用初始化列表来初始化成员 () : () {……} 没有其它办法将参数传递给. 情况和其实一样地道理.如果成员是一个常量对象或者引用也是一样.根据地规则,常量对象和引用不能被赋值,它们只能被初始化. 初始化列表与构造函数赋值地效率比较首先把数据成员按类型分类并分情况说明: .内置数据类型,复合类型(指针,引用) 在成员初始化列表和构造函数体内进行,两者在性能和结果上都是一样地 .用户定义类型(类类型) 两者在结果上相同,但是性能上存在很大地差别. 因为编译器总是确保所有成员对象在构造函数体执行之前初始化,所以对于用户自定义类型(类),在初始化列表中只会调用类地构造函数,在构造函数体中赋值就会先调用一次类地构造函数,然后再调用一次类地赋值操作符函数. 显然后者在性能上有所损失,特别对于构造函数和赋值操作符都需要分配内存空间地情况,使用初始化列表,就可以避免不必要地多次内存分配. 举个例子:假定你有一个类具有一个类型地成员,你想把它初始化为" .".你有两种选择: 、使用构造函数赋值()

构造函数的继承 C#

基类成员的初始化工作由基类的构造函数完成,派生类的初始化工作则有派生类的构造函数完成,这就产生了派生类构造函数的执行顺序问题,即当创建一个派生类的对象时,如何调用基类和派生类的构造函数分别完成各自成员的初始化。 派生类中的构造函数: 如果基类没有定义构造函数,派生类也可以不定义构造函数,全都采用默认的构造函数,此时,派生类新增成员的初始化工作可用其他公有函数来完成,如果只有派生类定义构造函数时,只需构造派生类对象即可。对象的基类部分使用默认构造函数来自动创建。 基类中的构造函数: 当基类和派生类都定义有构造函数时,情况就变得复杂了,同时也存在着继承规则。 1.如果基类中定义了构造函数,并且此构造函数没有参数,那么他可以隐式的被派生类继承,也就是说,派生类根本不需要包含构造函数,如下例子: namespace Syntaxtest { class Personclass { protected Personclass() { Console.WriteLine("基¨′类¤¨¤中D的ì?构1造¨?函?¥数oy被à?继¨?承D!ê?"); } } class Studentclass : Personclass { } class Program { static void Main(string[] args) { Studentclass t1 = new Studentclass(); } } } 运行结果:在基类中构造函数被继承 从运行结果来看,基类没有参数的构造函数被无条件继承,在派生类中被调用。

2.如果基类定义了带有参数的构造函数,则此构造函数必须被继承且在派生类中实现构造函数,提供一个将参数传递给基类构造函数的途径,以保证在基类进行初始化时能获得必须的数据,在实现构造函数时我们可以使用base关键字。代码如下: namespace Syntaxtest { class Personclass { protected Personclass(string T,string M) { Console.WriteLine("基¨′类¤¨¤中D的ì?构1造¨?函?¥数oy的ì?内¨2容¨Y!ê?"); Console.WriteLine("基¨′类¤¨¤中D的ì?构1造¨?函?¥数oy被à?继¨?承D!ê?"); Console.WriteLine("传??递ìY的ì?参?数oy:{0}",T); Console.WriteLine("传??递ìY的ì?参?数oy:{0}",M); } } class Studentclass : Personclass { public Studentclass(string N, string I):base(N,I) { Console.WriteLine("派¨|生|¨2类¤¨¤中D的ì?构1造¨?函?¥数oy的ì?内¨2容¨Y!ê?"); Console.WriteLine("参?数oy设|¨¨置?的ì?ID是o?:{0}", I); Console.WriteLine("参?数oy设|¨¨置?的ì?姓?名?是o?:{0}", N); } } class Program { static void Main(string[] args) { Studentclass t1 = new Studentclass("xusen","2010"); } } 运行结果: 基¨′类¤¨¤中D的ì?构1造¨?函?¥数oy的ì?内¨2容¨Y!ê? 基¨′类¤¨¤中D的ì?构1造¨?函?¥数oy被à?继¨?承D!ê 传递的参数:xusen 传递的参数:2010 派¨|生|¨2类¤¨¤中D的ì?构1造¨?函?¥数oy的ì?内¨2容¨Y!ê? 参数设置的姓名是:xusen 参数设置的ID是:2010

相关主题
文本预览
相关文档 最新文档