构造函数

C# base和this

…衆ロ難τιáo~ 提交于 2020-02-27 06:04:36
new关键字引起了大家的不少关注,尤其感谢 Anders Liu 的补充,让我感觉博客园赋予的交流平台真的无所不在。所以,我们就有必要继续这个话题,把我认为最值得关注的关键字开展下去,本文的重点是访问关键字(Access Keywords):base和this。虽然访问关键字不是很难理解的话题,我们还是有可以深入讨论的地方来理清思路。还是老办法,我的问题先列出来,您是否做好了准备。   • 是否可以在静态方法中使用base和this,为什么?   • base常用于哪些方面?this常用于哪些方面?   • 可以base访问基类的一切成员吗?   • 如果有三层或者更多继承,那么最下级派生类的base指向那一层呢?例如.NET体系中,如果以base访问,则应该是直接父类实例呢,还是最高层类实例呢?   • 以base和this应用于构造函数时,继承类对象实例化的执行顺序如何?   2. 基本概念   base和this在C#中被归于访问关键字,顾名思义,就是用于实现继承机制的访问操作,来满足对对象成员的访问,从而为多态机制提供更加灵活的处理方式。   2.1 base关键字   其用于在派生类中实现对基类公有或者受保护成员的访问,但是只局限在构造函数、实例方法和实例属性访问器中,MSDN中小结的具体功能包括:   • 调用基类上已被其他方法重写的方法。   •

浅谈面向对象特征

血红的双手。 提交于 2020-02-27 05:53:32
所有的面相对象思想,归根结底是为了简化代码,减少代码量,构建更符合现实生活逻辑的程序代码,从而减轻程序员的负担。不能一味地或者说刻意地去使用面相对象的思想而忽略了程序所实现的功能或者框架,要根据实际情况 众所周知,面向对象编程的特点为:封装、继承、多态。C#是一门完全面向对象的语言,由于比Java推出的时间还要晚,所以对面向对象的思想的体现比Java还要完美,那么在C#中如何体现封装、继承和多态呢?下面举例并进行说明。 1.封装 封装的好处有以下几点: ①数据不外泄,可以做到一定的保护 ②类的使用者不用考虑具体的数据运算,方便 ③程序结构性强,层次清晰,便于维护 对相关的字段、方法进行封装固然对面向对象编程起到不可缺少的重要作用,但并不代表不可以访问类或者说具体的实例化对象中的内容,而且为使用者提供接口,仅仅让他们调用就可以了,他们只做他们的工作,不需要考虑或者顾及你写的类具体是做什么的,更不用考虑你写的每一行代码是什么意思。 在C#中,对于变量的封装,往往将需要被在本类以外调用的,以属性的形式出现,而不像C++中是直接以public成员或者private成员加上相关的方法调用,那样要么不符合面向对象的特点,要么太麻烦。 C#中属性的声明: 代码如下: public class TestClass { public string Info { get; set; } }

构造函数不可虚,析构可以虚

痴心易碎 提交于 2020-02-27 04:41:01
一.什么是虚函数: 可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时, 基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数, 而不是基类中定义的成员函数(只要派生类改写了该成员函数)。 若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都 会调用基类中定义的那个函数。 例 class A { virtual void AAA() { cout<<"这是基类的!"; } }; class a:A { void AAA() { cout<<"这是派生类a!"; } }; 然后你生成a的实例,调用AAA()方法时,程序调用的是a中的AAA,而不是A中的AAA 如果你不定义virtual,在生成a的实例后调用的是基类的AAA() 二.构造函数不可定义为虚函数: 1,从存储空间角度 虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。 2,从使用角度 虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。

构造函数不可虚,析构可以虚

久未见 提交于 2020-02-27 04:34:05
一.什么是虚函数: 可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时, 基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数, 而不是基类中定义的成员函数(只要派生类改写了该成员函数)。 若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都 会调用基类中定义的那个函数。 例 class A { virtual void AAA() { cout<<"这是基类的!"; } }; class a:A { void AAA() { cout<<"这是派生类a!"; } }; 然后你生成a的实例,调用AAA()方法时,程序调用的是a中的AAA,而不是A中的AAA 如果你不定义virtual,在生成a的实例后调用的是基类的AAA() 二.构造函数不可定义为虚函数: 1,从存储空间角度 虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。 2,从使用角度 虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。

构造函数与析构函数

爷,独闯天下 提交于 2020-02-27 04:02:19
构造函数 构造函数是一种特殊的成员函数,它主要用于为对象分配存储空间,对数据成员进行初始化。每个类都有构造函数,即使没有声明它,编译器也会自动提供一个默认的构造函数。使用构造函数时需要注意以下几个问题 构造函数名与类名相同 构造函数没有返回类型 构造函数的主要作用是完成对类的对象初始化 创建类的对象时(用new关键字),系统自动调用构造函数,即必须使用操作符new来调用一个构造函数 构造函数可以重载 利用“:this()”和“:base()”,构造函数可以调用其他构造函数 构造函数可以标记为public、private、protected、internal或protected internal 静态构造函数用static修饰,既没有访问修饰符,也没有参数 析构函数 析构函数是当销毁一个类的时候调用的函数,它用来释放创建类所占有的资源。析构函数具有以下几个特点: 析构函数的名字和类名相同,只是前面需要加一个“~”符号 不能在结构中定义析构函数,只能对类使用析构函数 一个类只能有一个析构函数 析构函数无法继承或重载 程序员无法调用析构函数,它是被自动调用的 析构函数既没有修饰符,也没有参数 程序员无法控制何时调用析构函数,因为这是由垃圾回收器决定的。 来源: https://www.cnblogs.com/ahao214/p/5785863.html

构造函数为什么不能为虚函数 & 基类的析构函数为什么要为虚函数

亡梦爱人 提交于 2020-02-27 03:24:15
一、构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数相应一个指向vtable虚函数表的指针,这大家都知道,但是这个指向vtable的指针事实上是存储在对象的内存空间的。问题出来了,假设构造函数是虚的,就须要通过 vtable来调用,但是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。 2. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到相应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候可以变成调用子类的那个成员函数。而构造函数是在创建对象时自己主动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。 3. 构造函数不须要是虚函数,也不同意是虚函数,由于创建一个对象时我们总是要明白指定对象的类型,虽然我们可能通过实验室的基类的指针或引用去訪问它但析构却不一定,我们往往通过基类的指针来销毁对象。这时候假设析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。 4. 从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数从实际含义上看,在调用构造函数时还不能确定对象的真实类型(由于子类会调父类的构造函数);并且构造函数的作用是提供初始化,在对象生命期仅仅运行一次

C++第12章

白昼怎懂夜的黑 提交于 2020-02-27 03:04:19
第12章,类和动态内存的分配 12.1动态内存和类 12.1.1 复习范例和静态类成员 1,不能在类声明中初始化静态成员遍历变量,这是因为声明描述了如何分配内存,但是并不分配内存。同时对于静态类成员,可以在类声明之外使用单独的语句来进行初始化。但是如果静态成员是整型或枚举型const,则可以在类声明中初始化。 2,在构造函数中使用new来分配内存时,必须在相应析构函数中使用delete来释放内存。 如果使用new[](包括中括号)来分配内存,则应使用delete[](包括中括号)来释放内存。 3,注意如下代码:       StringBad sailor = sports; 等同于: StringBad sailor = StringBad(sports);因此相应的构造函数原型应该如下: StringBad (const StringBad &); 也就是说,当你使用一个对象来初始化另一个对象时,编译器将自动生成上述构造函数(称为复制构造函数,因为它创建对象的一个副本)。 12.1.2隐式成员函数 1,C++自动提供了下面这些成员函数: l 默认构造函数,如果没有定义构造函数。 l 复制构造函数,如果没有定义。 l 复制操作符,如果没有定义。 l 默认析构函数,如果没有定义。 l 地址操作符,如果没有定义 更准确的说,编译器将生成最后四个函数的定义

JavaScript引用类型与对象

萝らか妹 提交于 2020-02-26 23:18:44
1.引用类型 引用类型的值(对象)是引用类型的一个实例。引用类型有时候也被称为对象定义,因为它们描述的是一类对象所具有的属性和方法。 对象是某个特定引用类型的实例。新对象是使用new操作符后跟一个构造函数来创建的。 构造函数本身就是一个函数,只不过该函数是出于创建新对象的目的而定义的。 // 创建了 Object 引用类型的一个新实例,然后把该实例保存在了变量 person 中 // 使用的构造函数是 Object,它只为新对象定义了默认的属性和方法。 var person = new Object(); 大致地把JavaScript对象划分成“引用类型”、“基本包装类型”和“内置对象”三块内容。 引用类型:Object,Array,Date,RegExp,Function 基本包装类型:Boolean,Number,String 2.对象 在哪呢?在哪呢? 来源: https://www.cnblogs.com/amulong1237/p/12369755.html

C++笔记(3):一些C++的基础知识点

99封情书 提交于 2020-02-26 23:05:08
前言: 找工作需要,最近看了下一些C++的基本概念,为范磊的 《零起点学通C++》,以下是一些笔记。 内容:   delete p;只是删除指针p指向内存区,并不是删除指针p,所以p还是可以用的。删除空指针所指向内存是可以的。   堆中的变量和对象时匿名的,没有名称,只能通过指针来访问。   在堆中创建对象时,在分配内存的同时会调用类的构造函数,在删除堆中对象时,会调用类的析构函数。   为了避免内存泄露,在删除一个指针后应该将其其值赋为0。   常量指针是指针指向的内存区域地址不能改变,但是该内存地址里保存的值是可以改变的,比如int a; int * const p = &a;   指向常量的指针表示指针指向的对象是不能被修改的,但是该指针可以被修改,即该指针可以指向另一块目标内存地址。比如const int a = 0; const int *p = &a; 如果A是一个类,也可以为const A* p = new A;   而指向常量的常指针表示指针本身不能被修改,其指向的内存地址内容也不能被修改。比如const int a = 0; const int * const p = &a;   引用就是别名常量。   堆中的地址是用指针来操作的,用不到别名。   如果在main函数前面的其它函数的声明和定义是一起的,则表明这个函数是内联函数!因此当该函数较长时

c++中的右值引用的简单理解

纵然是瞬间 提交于 2020-02-26 22:00:09
以下的内容是我看了网上的博文后自己的总结,如果时间充裕的话,建议直接看 原文 。 简介:   c++中的右值引用十分不好理解,但是当你大概知道右值引用解决了c++中的什么问题后,会感觉右值引用还是很有用的。平时我们在c++中使用的引用为了和c++11引入的右值引用区分,一般把它称之为左值引用。左值引用很好理解,就是多个变量名绑定到了同一块内存上,操作这几个不同的变量名相当于操作同一块内存。但是右值引用就让人有点摸不着头脑了,一是右值(可以简单地认为就是字面常量或者临时变量)根本就没有变量名,这怎么引用?二是左值引用已经解决了按值传参的缺陷,右值引用又是干嘛的?正是由于这些问题让人感觉难以理解,我们需要分解问题,一步步去理解它。先复习一下什么是左值和右值。知道了左值右值的概念后,直接讲右值引用还是会感觉有点晦涩难懂,所以先引入一个move语义的概念,然后给出一个场景,再去看右值引用存在的意义。 左值和右值的区别:   区分左值和右值最简单的办法就是看一个内存空间是否可以使用&符号取得它的地址。能取到的就是左值,取不到的就是右值。比如    什么是move语义:   假设我们有一个这样的class:它里面包含着一个 int *m_memory 的成员变量,指向一块从堆上分配来的内存,并且假设这块内存有点大,复制一份这块内存中的字节需要一定的时间。