精华内容
下载资源
问答
  • 构造函数与析构函数的调用顺序 子类对象调用父类的成员 2. 父类类型的引用或者指针,子类对象初始化父类类型的对象 3. 给父构造函数传参,同时给对象赋值 2.继承的权限 笔记描绘了继承权限的关系 3.继承的...

    NDK开发汇总

    一 类

    C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,用户定义的类型。

    class Student {
    	int i;    //默认 private
    public:
    	Student(int i,int j,int k):i(i),j(j),k(k){};	//构造方法 
    	~Student(){};	//析构方法 
    private:
    	int j;
    protected:
    	int k;
    };
    
    Student student(1,2,3); //调用构造方法 栈
    //出方法释放student 调用析构方法
    
    //动态内存(堆)
    Student *student = new Student(1,2,3);
    //释放
    delete student;
    student = 0;
    

    类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行(不需要手动调用)。

    private:可以被该类中的函数、友元函数访问。 不能被任何其他访问,该类的对象也不能访问。

    protected:可以被该类中的函数、子类的函数、友元函数访问。 但不能被该类的对象访问。

    public:可以被该类中的函数、子类的函数、友元函数访问,也可以被该类的对象访问。

    查看内存:

    adb shell 进入,命令: dumpsys meminfo 包名

    MyTeacher teacher;

    • C++中 这个语句执行完毕,在当前的堆内存内 初始化并且赋值好该对象
    • 在java中执行这个语句,只是开辟了一块内存空间,并没初始化和赋值对象,
      必须用new关键字,来进行初始化和赋值

    二 引用

    Teacher.h

    class MyTeacher
    {
    public:
    	
    	~MyTeacher();//析构函数 释放在构造函数里面动态申请的内存 (free)
    
    	MyTeacher(int age,char *name); 
    
    	void setAge(int age);
    	int getAge();
    	void setName(char *name);
    	char* getName();
    
    private:
    	int age;
    	char *name;
    };
    

    Teacher.cpp

    #include <Teacher.h>
    #include <iostream>
    
    //c++ 标准库的命名空间
    using namespace std;
    
    MyTeacher::MyTeacher(int age,char *name):name(name),age(age) {
    	cout << " MyTeacher 构造函数  地址:" << this << endl;
    }
    
    MyTeacher::~MyTeacher() {
    	cout << " MyTeacher 析构函数 地址:" << this << endl;
    }
    // ::代表限定符
    void MyTeacher::setAge(int age) {
    	this->age = age;
    }
    
    int MyTeacher::getAge() {
    	return this->age;
    }
    
    void MyTeacher::setName(char *name) {
    	this->name = name;
    }
    
    char* MyTeacher::getName() {
    
    	return this->name;
    }
    

    调用:

    #include <Teacher.h>
    #include <iostream>
    
    using namespace std;
    
    void fun() {
    	MyTeacher teacher = MyTeacher(18, "zhangsan");
    
    	cout << "teacher name:" << teacher.getName() << endl;
    	cout << "teacher age:" << teacher.getAge() << endl;
    }
    
    void main() {
    
    	fun();
    
    	system("pause");
    }
    

    结果:

     MyTeacher 构造函数  地址:00D7F884
    teacher name:zhangsan
    teacher age:18
     MyTeacher 析构函数 地址:00D7F884
    

    三 指针

    void fun() {
    
    	MyTeacher *teacher = new MyTeacher(18, "zangsan");
    	cout << "teacher name:" << teacher->getName() << endl;
    	cout << "teacher age:" << teacher->getAge() << endl;
    	//	delete teacher;
    //	teacher = nullptr;
    }
    

    结果:

     MyTeacher 构造函数  地址:0113E950
    teacher name:zangsan
    teacher age:18
    

    没有调用析构函数,需要delete teacher;才会调用

    四 拷贝构造函数

    使用场景

    1. 值传递
    2. 赋值语句
      MyStudent.h
    class MyStudent
    {
    public:
    	MyStudent(int age,char *name,char *teacherName);
    	~MyStudent();
    	//重写默认的拷贝构造函数
    	MyStudent(const MyStudent &student);
    public:
    	int age;
    	char *name;
    	char *teacherName;
    };
    
    

    MyStudent.cpp

    #include <MyStudent.h>
    #include <iostream>
    
    using namespace std;
    MyStudent::MyStudent()
    {
    	cout << " MyStudent 构造函数  地址:" << this << endl;
    }
    
    MyStudent::~MyStudent()
    {
    	cout << " MyStudent 析构函数  地址:" << this << endl;
    }
    
    //默认构造函数 浅拷贝
    MyStudent::MyStudent(const MyStudent &student) {
    	cout << " MyStudent 拷贝构造函数  地址:" << this << endl;
    	this->age = student.age;
    	this->name = student.name;
    	this->teacherName = student.teacherName;
    }
    

    调用:

    void setFunX(MyStudent student) {
    	cout << "setFunc student name:" << student.name << endl;
    	cout << "setFunc student age:" << student.age << endl;
    	cout << "setFunc student teacherName:" << student.teacherName << endl;
    }
    void main() {
    	MyStudent  student = MyStudent(21, "jack", "Jone");
    	setFunX(student);
    
    	system("pause");
    }
    
    

    结果:

     MyStudent 构造函数  地址:008FFE74
     MyStudent 拷贝构造函数  地址:008FFD88
    setFunc student name:jack
    setFunc student age:21
    setFunc student teacherName:Jone
     MyStudent 析构函数  地址:008FFD88
    

    五 浅拷贝与深拷贝

    • 默认的拷贝构造函数是浅拷贝
      浅拷贝:
    void copyTest(){
     MyStudent  student = MyStudent(21, "jack", "Jone");
     MyStudent st2 = student;
     }
    

    在这里插入图片描述
    浅拷贝出现的问题
    修改构造、析构函数

    MyStudent::MyStudent(int age, char *name, char *teacherName):age(age)
    {
    	cout << " MyStudent 构造函数  地址:" << this << endl;
    	int len = strlen(name);
    	this->name = (char *)malloc(len + 1);
    
    	strcpy(this->name, name);
    
    	len = strlen(teacherName);
    	this->teacherName = (char *)malloc(len + 1);
    	strcpy(this->teacherName, teacherName);
    }
    
    MyStudent::~MyStudent()
    {
    	cout << " MyStudent 析构函数  地址:" << this << endl;
    	free(this->name);
    	free(this->teacherName);
    }
    

    错误:

    C4996	'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.	Project2	c:\users\pf0zybaj\source\repos\project2\project2\src\mystudent.cpp	11
    

    解决:属性 ->C/C+±>命令行 :-D _CRT_SECURE_NO_WARNINGS ->应用

    继续运行,打印正常,任意键退出时对报错,free已经释放了,拷贝构造函数执行了,拷贝对象释放野指针释放出错

    为了避免浅拷贝出现的问题有两个解决方法:
    1 深拷贝

    MyStudent::MyStudent(const MyStudent &student) {
    	cout<<"MyStudent 深拷贝构造函数 地址:" << this << endl;
    	int len = strlen(student.name);
    	this->name = (char *)malloc(len + 1);
    
    	strcpy(this->name, student.name);
    
    	len = strlen(student.teacherName);
    	this->teacherName = (char *)malloc(len + 1);
    	strcpy(this->teacherName, student.teacherName);
    }
    
    

    2 私有化拷贝构造函数(不常用)

    六 Demo

    NDK13_C++基础:构造函数、拷贝构造函数、浅拷贝

    展开全文
  • c++构造函数详解

    2020-04-27 17:48:18
    一 构造函数的种类 (1)无参数构造函数 ...构造函数可以有各种参数形式,一个类可以有多个构造函数,前提是参数的个数,类型,顺序不同 (3)拷贝构造函数 拷贝构造函数的参数表为对象本身的引用,用于根据一...

    一  构造函数的种类

    (1)无参数构造函数

    1. 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做
    2. 只要你写了一个某一种构造函数,系统就不会再自动生成这样一个默认的构造函数

    (2)重载构造函数

    1. 构造函数可以有各种参数形式,一个类可以有多个构造函数,前提是参数的个数,类型,顺序不同

    (3)拷贝构造函数

    1.  拷贝构造函数的参数表为对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象
    2. 若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险(属于浅拷贝)
    3. 类的对象需要拷贝时,拷贝构造函数将会被调用
    4. (1)一个对象以值传递的方式传入函数体 
      (2)一个对象以值传递的方式从函数返回 
      (3)一个对象需要通过另外一个对象进行初始化。
    5. 浅拷贝与深拷贝

    二   构造函数的继承

    1. 子类不会继承父类的构造方法
    2. 子类创建对象时,先执行父类无参的构造方法,然后执行子类的构造方法,如果父类只有有参数的构造方法,则子类必须显示调用此带参构造方法
    3. 子类调用父类构造方法,其实只是一种函数调用,服务的还是子类的对象
    4. 继承构造函数不会继承参数的默认值
    //(1)透传继承
    struct A
    {
      A(int i) {}
      A(double d,int i){}
      A(float f,int i,const char* c){}
      //...等等系列的构造函数版本号
    };
    
    struct B:A
    {
      B(int i):A(i){}
      B(double d,int i):A(d,i){}
      B(folat f,int i,const char* c):A(f,i,e){}     //A(f,i,e)是实参     
      //......等等好多个和基类构造函数相应的构造函数
    };
    
    //栗子
    Son(string name, char sex, int age, int height, int tall) :Parent(name, sex, age)
    {
    		this->height = height;
    		this->tall = tall;
    }
    //(2)使用using
    struct A
    {
      A(int i) {}
      A(double d,int i){}
      A(float f,int i,const char* c){}
      //...等等系列的构造函数版本号
    };
    struct B:A
    {
      using A::A;
      //关于基类各构造函数的继承一句话搞定
      //......
    };
    //当使用using语句继承基类构造函数时。派生类无法对类自身定义的新的类成员进行初始化,我们可使用类成员
    的初始化表达式,为派生类成员设定一个默认初始值
    //(3)解决重复定义
    struct A
    {
        A(int){}
    };
    
    struct B
    {
        B(int){}
    };
    
    struct C:A,B
    {
        using A::A;                   //这不同于钻石继承的难题,例如,A,B中都有个name参数,那么在C中,
        using B::B;                      会出现两次this.name=name,这个this是指C的对象, 子类调用
        C(int i):A(i),B(i) {}              父类构造函数,仅仅只是为了方便子类对象属性的初始化//
    };
    
    //A 和B 的构造函数会导致C 中重复定义相同类型的继承构造函数。
    解决方法是让继承类进行显示定义构造函数。
    

     

     

     

     

     

     

     

     

    展开全文
  • 构造函数和析构函数 系统自动调用。 被声明为公有成员函数。 构造函数可被重载为多个,析构函数只能有一个。... 拷贝构造函数:用已存在的对象初始化新建立的对象。 拷贝构造函数的调用: 对象初始...

    构造函数和析构函数

    • 系统自动调用。
    • 被声明为公有成员函数。
    • 构造函数可被重载为多个,析构函数只能有一个。
    • 对象消失时的清理工作不是析构函数来完成的,而是用户在析构函数内增加清理语句完成的。(delete)
    • 先建立全局变量,再建立局部变量,建立对象时系统自动调用构造函数,析构函数的调用顺序与构造函数相反。
    • 拷贝构造函数:用已存在的对象初始化新建立的对象。
    • 拷贝构造函数的调用:
    1. 对象初始化另一个新建对象。
    2. 将对象作为实参传递给形参时。
    3. 函数执行结束时作为返回值返回时。

         ——当对象最为函数的返回值时需要调用拷贝构造函数,此时c++将从堆中动态建立一个临时对象,将函数返回的对象复制给该临时对象,并把该临时对象的地址存储到寄存器中,从而由该临时对象完成函数返回值的传递。

    • 如果是已存在的对象间的调用,拷贝构造函数不会被调用(只是简单的覆盖)。
    • 建立对象时拷贝构造函数与构造函数只有一个被调用。
    • 重新定义拷贝构造函数后,默认拷贝拷贝构造函数与默认构造函数就不存在了。
    • 重新定义构造函数后,默认拷贝构造函数还存在。
    • 对象间的赋值不调用拷贝构造函数,而是结构式的拷贝。
    • 对象的引用在定义时一般要初始化(除非作为函数参数与函数返回值),且不调用构造函数。                                                  格式:  类名 & 对象引用名  = 被调用的对象;
    展开全文
  • 多重继承的问题:多个类B,C,…继承同一个类A导致如果X继承了B,C,…那么在X中将还有多个A中成员的拷贝,如果想要访问A中的成员如果不加名字空间将会导致二义性,这种拷贝大多是没有实际意义的,为了避免这种空间浪费...

    多重继承的问题:多个类B,C,…继承同一个类A导致如果X继承了B,C,…那么在X中将还有多个A中成员的拷贝,如果想要访问A中的成员如果不加名字空间将会导致二义性,这种拷贝大多是没有实际意义的,为了避免这种空间浪费,C++有虚继承机制。

    如果B,C…继承A,那么让B,C…都是虚继承(在继承权限前面加上virtual),这样当X继承B,C…的时候就不会出现多份拷贝。

    需要注意的是,需要虚继承的是B,C等这些继承同一个类的派生类而不是X

    构造函数和析构函数顺序

    详细可以参阅《C++Primer》[第五版]720-721页相关内容

    构造顺序:

    首先按照基类中声明顺序,初始化所有的虚基类,然后再按照顺序初始化所有的非虚基类。如果有在构造函数中调用有参构造函数就调用有参构造函数,否则调用无参构造函数。

    虚基类是由最底层的派生类初始化的,即可能在虚基类继承路径上每个派生类都有对虚基类的初始化,但是当一个类继承了虚基类时,由它控制对虚基类的初始化,如果它不进行初始化,会调用虚基类的无参构造函数进行初始化。(而不是其他基类,就算它的构造函数中有对虚基类的初始化)

    析构的顺序和构造函数的顺序相反。

    原理

    但是虚继承是如何实现的呢?在网上查找资料后记录一下自己的理解(可能不是很准确,但是可能会帮助理解问题):

    学术的说:虚继承通过虚基类指针(占四个字节)和虚基类表(不占类的字节)实现。虚基类表中记录了虚基类与本类的偏移地址,虚基类指针指向虚基类表,通过偏移地址就找到了虚基类成员,从而实现虚继承。

    可能有点难以理解,我的理解就是,派生类地址可能一般不是和基类在一起的,仅仅是通过构造函数等实现对基类成员的继承。而虚基类地址可能地址就在基类后面。

    假设我们有基类A,虚基类B,C,以及B,C的派生类类D
    每次我们创建D的时候先创建基类A的成员,然后通过需基类指针和虚基类表找到虚基类B的地址创建他特有的成员,然后再找到C的地址创建他特有的成员,这样就不会将A中的成员重复创建,实现了虚继承。

    因为要保存虚基类指针的缘故,每个虚基类中都多出四个字节用来保存虚基类指针。(虚基类表不需要在类中保存)。虚基类的派生类都会包含这个虚基类指针,因此每多继承以一个虚基类就会多一个虚基类指针,空间就会多4。

    展开全文
  • Vector叫法很=向量,顺序表,可变数组 1、特点是数据是连续存储的; 2、是一动态数组,例如本来创建一10大小的数组,发现不够用了,它就创建一大一点的数组,把原来的数据复制过来 Vector的实现 构造...
  •     成员变量总是按照在类定义中的声明顺序进行初始化,构造函数中的初始化列表的顺序被忽略。这么做的原因是需要确保用唯一的顺序销毁成员。一成员的初始化尽量不要依赖于其他成员。 如果违反这条...
  • 12对象的构造和析构

    2017-05-25 14:14:58
    3拷贝构造函数 4默认构造函数 5调用规则 深拷贝和浅拷贝 多个对象构造和析构 调用顺序 对象的动态管理 1.基本概念  创建一个对象时,常常需要作某些初始化的工作,例如对数据成员赋初值。注意,类的数据成员是不能...
  • 1.构造函数的执行顺序?...如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序,而不是它们出现在成员初始化表中的顺序。 派生类构造函数。 析构函数顺序 调用派生类的析构函数; ...
  • 2.final变量必须在构造函数返回之前初始化,但不保证构造函数中的指令顺序 3.匿名内部类使用外部变量(参数或者变量都会被拷贝)时的final修饰 为了提示用户 该变量可能涉及线程修改 volatile: 1.禁止指令重排序 ...
  • C++关于类的一些笔记

    2015-05-09 15:50:27
    1. 友元函数不能之间访问对象数据成员,也不能通过this指针访问,只能用函数参数传递进来(访问规则和成员函数一致) 2. 派生类继承基类的成员,访问权限为...5. 类的构造函数调用顺序遵循:先调用基类,如果继承多个
  • 与C++类相关的知识点

    2021-03-17 16:11:56
    文章目录什么是虚函数?什么是纯虚函数?...为什么拷贝构造函数必须为引用?C++类对象的初始化顺序如何禁止一类被实例化?为什么用成员初始化列表会快一些?初始化数据成员与对数据成员赋值的含义是
  • 包含中文版和英文原版 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 态性 2 1.1.4 操作概念:OOP程序...10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针
  • C++ 面试题总结

    2017-12-17 23:35:00
    1 dynamic_cast 与 static_cast 区别 2 static,const,int &, int 初始化方式,初始化...5 拷贝构造函数与赋值构造函数的实现 6 纯虚函数如何实现,抽象类能否被实例化,为什么不能实例化。 virtual void prin...
  • 1、题目描述 2、分析 第一次碰到这种类似于设计一类的题目,题目要求实现两...构造函数里需要用nums对这变量进行初始化,初始化的方法可以有很,可以使用列表初始化、也可以使用拷贝构造函数。这样rese...
  • 2021-04-03

    2021-04-03 18:06:32
    引用的实现,拷贝构造函数的调用 ,析构函数的调用,默认构造函数的调用的先后顺序 1引用与析构函数的先后顺序 template List& List::operator+(List& p); 在这“+”好运算符重载的函数中(不知道算不算...
  • 1.构造函数通过函数重载的机制可以有多个(不同的构造函数,参数个数,或者参数类型不同。),但是析构函数只能有一个。当没有在代码中写明构造或析构函数时,编译器会自动生成缺省的构造或析构函数。构造函数和析构...
  • 学习C++有一段时间,根据经验来说,关键还是基础,高楼万丈平地起,切记浮躁,一步一个脚印,从最基本的知识的开始,大道理不讲,所有的每点都很重要,下面我们就看看C++需要学习那些. 一、内联函数函数重载...
  • C++第三天

    2019-10-05 17:51:00
    复习拷贝构造函数03. 转换构造函数04. 第一单继承05. 更加完整的例子06. 继承方式 - 公有07. 继承方式 - 私有08. 继承方式 - 保护09. 修改访问属性0A. 对不可访问的探索0B. 构造和析构的顺序0C. 成员的重定义0D. ...
  • 目 录 译者序 前言 第1章 对象的演化 1.1 基本概念 1.1.1 对象:特性+行为 1.1.2 继承:类型关系 1.1.3 态性 1.1.4 操作概念:OOP程序像什么 ...10.3.4 拷贝构造函数方法的选择 10.4 指向成员的指针
  • C++的OOP总结

    2019-09-05 10:03:46
    目录前言单类构造析构及初始化列表浅拷贝深拷贝赋值运算符重载几重要的临时对象例子解析例1:默认拷贝构造产生临时对象例2:赋值运算符重载、拷贝构造设置不当产生临时对象、类内对象初始化列表例3:const修饰的...
  • C++编程思想

    2014-10-23 09:50:07
    目 录 译者序 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 态性 2 1.1.4 操作概念:OOP程序像什么 3 ...10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针
  • C++编程思想.rar

    2014-05-06 17:02:48
    目 录 译者序 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 态性 2 1.1.4 操作概念:OOP程序像什么 3 ...10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针
  • C++编程思想.pdf

    热门讨论 2013-08-09 17:15:36
    C++编程思想 目 录 译者序 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 态性 2 ...10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针 ......
  • C++高级参考手册

    2013-06-05 17:46:53
    目 录 译者序 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 态性 2 1.1.4 操作概念:OOP程序像什么 3 ...10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针
  • c++编程思想

    2012-08-16 23:40:28
    1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 态性 2 1.1.4 操作概念:OOP程序像什么 3 1.2 为什么C++会成功 3 ...10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 215
精华内容 86
关键字:

多个拷贝构造函数拷贝顺序