精华内容
下载资源
问答
  • new创建类对象与直接定义的区别

    千次阅读 2016-11-11 14:03:40
    new创建类对象需要指针接收,一处初始化,多处使用new创建类对象使用完需delete销毁new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间new对象指针用途广泛,比如作为函数返回值、函数参数等频繁调用...

    new创建对象的特点

    • new创建类对象需要指针接收,一处初始化,多处使用
    • new创建类对象使用完需delete销毁
    • new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间
    • new对象指针用途广泛,比如作为函数返回值、函数参数等
    • 频繁调用场合并不适合new,就像new申请和释放内存一样

    new创建类对象实例

    1、new创建类对象例子:

    CTest* pTest = new CTest();
    
    delete pTest;
     
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    pTest用来接收类对象指针。

    不用new,直接使用类定义申明:

    CTest mTest;
     
    • 1
    • 1

    此种创建方式,使用完后不需要手动释放,该类析构函数会自动执行。而new申请的对象,则只有调用到delete时再会执行析构函数,如果程序退出而没有执行delete则会造成内存泄漏。

    2、只定义类指针

    这跟不用new申明对象有很大区别,类指针可以先行定义,但类指针只是个通用指针,在new之前并为该类对象分配任何内存空间。比如:

    CTest* pTest = NULL;
     
    • 1
    • 1

    但使用普通方式创建的类对象,在创建之初就已经分配了内存空间。而类指针,如果未经过对象初始化,则不需要delete释放。

    3、new对象指针作为函数参数和返回值

    下面要示意一下类指针对象作为返回值和参数使用。

    class CTest 
    {  
    public:   
        int a;  
    };    
    
    class CBest 
    { 
    public:  
        int b;  
    };   
    
    CTest* fun(CBest* pBest) 
    {   
        CTest* pTest = new CTest();   
        pTest->a = pBest->b;
        return pTest;  
    }    
    
    int main() 
    {   
        CBest* pBest = new CBest();   
        CTest* pRes= fun(pBest);     
    
        if(pBest!=NULL)    
            delete pBest;   
    
        if(pRes!=NULL)    
            delete pRes ;   
    
        return -1;  
    }
    展开全文
  • C++编程语言中创建类对象(类的初始化)的方法

    万次阅读 多人点赞 2018-08-07 21:03:55
    本文主要介绍在 C++ 编程语言中,创建类对象(类的初始化)的两种方法,这两种方法分别为:“直接使用类名创建对象”和“使用 new 关键字创建对象”。 1 概述 “直接使用类名创建对象”和“使用 new 关键字创建...

    本文主要介绍在 C++ 编程语言中,创建类的对象(类的初始化)的两种方法,这两种方法分别为:“直接使用类名创建对象”和“使用 new 关键字创建对象”。

    1 概述

    “直接使用类名创建对象”和“使用 new 关键字创建对象”两种方法的区别如下:

    • 使用 new 关键字创建的对象会赋值给类指针,此对象可在多处使用;
    • 使用 new 关键字创建的对象在使用完成后,必须要使用 delete 销毁该对象,否则会造成内存泄露(new 申请的对象,只有调用到 delete 时才会执行析构函数);而直接使用类名创建的对象,则不需要手动销毁该对象,因为该类的析构函数会自动执行;
    • 使用 new 关键字创建的对象使用的是堆空间;而在局部、直接使用类名创建的对象则使用栈空间;
    • 使用 new 关键字创建的对象会赋值给类指针,该指针用途广泛,比如作为函数返回值、函数参数等;
    • 频繁调用(不同)对象的场合并不适合使用 new 方法创建对象,原理同 new 申请和 delete 释放内存。

    综上,在决定使用哪种方式创建类的对象时,需要根据实际的应用场景,选择合适的方法。

    2 示例代码

    这里编写了一份简单的示例代码,展示了“直接使用类名创建对象”和“使用 new 关键字创建对象”两种创建类的对象的方法。

    示例代码(class_init_test1.cpp)的内容如下:

    #include "iostream"
    #include "string"
    
    using namespace std;
    
    class ClassOne
    {
    public:
        int m_one;
    public:
        void PrintSomething(const string& strInput, const int& nInput);
    };
    
    void ClassOne::PrintSomething(const string & strInput, const int & nInput)
    {
        cout << strInput << nInput << endl;
    }
    
    
    int main()
    {
        // 直接使用类名创建对象
        ClassOne c1;
        c1.m_one = 1;
        string strSomething = "m_one value is: ";
        c1.PrintSomething(strSomething, c1.m_one);
    
        // 使用new创建对象
        ClassOne *c2 = new ClassOne();
        c2->m_one = 2;
        c2->PrintSomething(strSomething, c2->m_one);
        if (NULL != c2)
        {
            // 使用delete删除对象
            delete c2;
            c2 = NULL;
        }
    
        return 0;
    }
    
    

    编译并运行上述代码,运行结果如下:

    展开全文
  • JS创建类对象

    千次阅读 2018-07-08 17:31:34
    JavaScript 创建类/对象的几种方式在JS中,创建对象(Create Object)并不完全是我们时常说的创建类对象,JS中的对象强调的是一种复合类型,JS中创建对象及对对象的访问是极其灵活的。JS对象是一种复合类型,它允许...
    JavaScript 创建类/对象的几种方式
    在JS中,创建对象(Create Object)并不完全是我们时常说的创建类对象,JS中的对象强调的是一种复合类型,JS中创建对象及对对象的访问是极其灵活的。
    JS对象是一种复合类型,它允许你通过变量名存储和访问,换一种思路,对象是一个无序的属性集合,集合中的每一项都由名称和值组成(听起来是不是很像我们常听说的HASH表、字典、健/值对?),而其中的值类型可能是内置类型(如number,string),也可能是对象。
    一、由一对大括号括起来
        var emptyObj = {};
        var myObj =
        {
            'id': 1,        //属性名用引号括起来,属性间由逗号隔开
            'name': 'myName'
        };
        //var m = new myObj(); //不支持

      不知你注意到对象都是用 var 声明的没有,像上面的代码,就只是简单的声明一个对象,它只有一份拷贝,你不能像实例化类对象一样对它采用new操作,像上面代码的注释部分。这样就极大的限制了对象的重用,除非你建立的对象只需要一份拷贝,否则考虑用其他方法建立对象。

      下面一起看看如何访问对象的属性和方法。

        var myObj =
        {
            'id': 1,
            'fun': function() {
                document.writeln(this.id + '-' + this.name);//以"对象.属性"方式访问
            },
            'name': 'myObj',
            'fun1': function() {
                document.writeln(this['id'] + '+' + this['name']);//以集合方式访问
            }
        };
        myObj.fun();
        myObj.fun1();
        // 结果
        // 1-myObj 1+myObj 

    二、用 function 关键字模拟 class

     function 中用 this 引用当前对象,通过对属性的赋值来声明属性。如果用var声明变量,则该变量为局部变量,只允许在类定义中调用。

            function myClass() {
                this.id = 5;
                this.name = 'myclass';
                this.getName = function() {
                    return this.name;
                }
            }
            var my = new myClass();
            alert(my.id);
            alert(my.getName());
            // 结果
            // 5
            // myclass

    三、在函数体中创建一个对象,声明其属性再返回

    在函数体中创建对象可利用第一点的方法,或先 new Object(); 再为各属性赋值。

    不过用这种方式创建的对象在VS2008 SP1中是没有智能提示的。

            function myClass() {
                var obj =
                {
                    'id':2,
                    'name':'myclass'
                };
                return obj;
            }
            function _myClass() {
                var obj = new Object();
                obj.id = 1;
                obj.name = '_myclass';
                return obj;
            }
            var my = new myClass();
            var _my = new _myClass();
            alert(my.id);
            alert(my.name);
            alert(_my.id);
            alert(_my.name);
    
            // 结果
            // 2
            // myclass
            // 1
            // _myclass

    一、定义类或对象
    1.
    工厂方式
    创建对象car 
    var oCar = new Object;
    oCar.color = "red";
    oCar.doors = 4;
    oCar.mpg = 23;
    oCar.showColor = function(){
       alert(this.corlor);
    };

    创建多个car
    function createCar(color, doors, mpg) {
        var tempcar = new Object;
        tempcar.color = color;
        tempcar.doors = doors;
        tempcar.mpg = mpg;
        tempcar.showColor = function () {
            alert(this.color)
        };
       return tempcar;
    }

    var car1 = createCar("red", 4, 23);
    var car2 = createCar("blue", 3, 25);
    car1.showColor();    //outputs "red"
    car2.showColor();    //outputs "blue"
    这个例子中,每次调用函数createCar(),都要创建新函数showColor(),意味着每个对象都有自己的showColor()版本,事实上,每个对象都共享了同一个函数。
    有些开发者在工厂函数外定义对象的方法,然后通过属性指向该方法,从而避开这个问题。
    function showColor(){
       alert(this.color);
    }
    function createCar(color, doors, mpg) {
        var tempcar = new Object;
        tempcar.color = color;
        tempcar.doors = doors;
        tempcar.mpg = mpg;
        tempcar.showColor = showColor;
        return tempcar;
    }

    var car1 = createCar("red", 4, 23);
    var car2 = createCar("blue", 3, 25);
    car1.showColor();    //outputs "red"
    car2.showColor();    //outputs "blue"
    从功能上讲,这样解决了重复创建函数对象的问题,但该函数看起来不像对象的方法。所有这些问题引发了开发者定义的构造函数的出现。

    2.构造函数方法
    function Car(sColor, iDoors, iMpg) {
        this.color = sColor;
        this.doors = iDoors;
        this.mpg = iMpg;
        this.showColor = function () {
            alert(this.color)
        };
    }

    var oCar1 = new Car("red", 4, 23);
    var oCar2 = new Car("blue", 3, 25);
    oCar1.showColor();    //outputs "red"
    oCar2.showColor();    //outputs "blue"
    就像工厂函数,构造函数会重复生成函数,为每个对象都创建独立的函数版本。不过,也可以用外部函数重写构造函数,同样,这么做语义上无任何意义。

    3.原型方式
    function Car(){
    }
    Car.prototype.color = "red";
    Car.prototype.doors= 4;
    Car.prototype.mpg= 23;
    Car.prototype.showColor = function(){
       alert(this.color);
    }

    var oCar1 = new Car();
    var oCar2 = new Car();
    它解决了前面两种方式存在的两个问题。但并不尽人意。首先,这个构造函数没有参数。使用原型方式时,不能通过构造函数传递参数初始化属性的值,这点很令人计厌,但还没完,真正的问题出现在属性指向的是对象,而不是函数时。考虑下面的例子:
    function Car(){
    }
    Car.prototype.color = "red";
    Car.prototype.doors= 4;
    Car.prototype.mpg= 23;
    Car.prototype.drivers = new Array("Mike","Sue");
    Car.prototype.showColor = function(){
       alert(this.color);
    }

    var oCar1 = new Car();
    var oCar2 = new Car();
    oCar1.drivers.push("Matt");
    alert(oCar1.drivers);      //outputs "Mike,Sue,Matt"
    alert(oCar2.drivers);      //outputs "Mike,Sue,Matt"

    4.
    混合的构造函数/原型方式
    function Car(sColor, iDoors, iMpg) {
        this.color = sColor;
        this.doors = iDoors;
        this.mpg = iMpg;
        this.drivers = new Array("Mike", "Sue");
    }

    Car.prototype.showColor = function () {
        alert(this.color);
    };

    var oCar1 = new Car("red", 4, 23);
    var oCar2 = new Car("blue", 3, 25);

    oCar1.drivers.push("Matt");

    alert(oCar1.drivers);    //outputs "Mike,Sue,Matt"
    alert(oCar2.drivers);    //outputs "Mike,Sue"
    现在就更像创建一般对象了。所有的非函数属性都有构造函数中创建,意味着又可用构造函数的参数赋予属性默认值了。因为只创建showColor()函数的一个实例,所以没有内存浪费。

    5.动态原型方法
    function Car(sColor, iDoors, iMpg) {
        this.color = sColor;
        this.doors = iDoors;
        this.mpg = iMpg;
        this.drivers = new Array("Mike", "Sue");

        if (typeof Car._initialized == "undefined") {

            Car.prototype.showColor = function () {
                alert(this.color);
            };

            Car._initialized = true;
        }
    }


    var oCar1 = new Car("red", 4, 23);
    var oCar2 = new Car("blue", 3, 25);

    oCar1.drivers.push("Matt");

    alert(oCar1.drivers);    //outputs "Mike,Sue,Matt"
    alert(oCar2.drivers);    //outputs "Mike,Sue"
    动态原型方法的基本想法与混合的构造函数/原型方式相同,即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。唯一的区别是赋予对象方法的位置。

    6.混合工厂方式
    这种方式通常是在不能应用前一种方式时的变通方法。它的目的是创建假构造函数,只返回另一种对象的新实例。
    function Car() {
        var tempcar = new Object;
        tempcar.color = "red";
        tempcar.doors = 4;
        tempcar.mpg = 23;
        tempcar.showColor = function () {
            alert(this.color)
        };
       return tempcar;
    }
    与经典方式不同,这种方式使用new运算符,使它看起来像真正的构造函数。

    7.采用哪种方式
       
    如前所述,目前使用最广泛的是混合的构造函数/原型方式。些外,动态原型方法也很流行,在功能上与前者等价,可以采用这两种方式中的任何一种。

    二、修改对象
    1.
    创建新方法
    可以用prototype属性为任何已有的类定义新方法,就像处理自己的类一样。
    例:
    Array.prototype.indexOf = function(vItem){
       for(var i=0;i<this.length;i++){
          if(vItem == this[i]){
             return i;
          }
       }
       retunr -1;
    }
    最后,如果想给ECMAScript中的每个本地对象添加新方法,必须在Object对象的prototype属性上定义它。

    2.重定义已有方法
    就像能给自己的类定义新方法一样,也可重定义已有的方法。函数名只是指向函数的指针,因此可以轻易地使它指向其他函数。

    Function.prototype.toString = function(){
       return "Function code hidden";
    }
    function sayHi(){
       alert("hi");
    }
    alert(sayHi.toString());      //outputs "Function code hidden"

     

     

    Class - 类创建

    Class类实现了在JavaScript中声明一个新的类并通过构造函数实例化这个类的机制。通过使用Class.create()方法你实际上声明了一个新的类并定义了一个initialize()方法作为构造函数一旦你在这个声明的类的prototype中实现了改该方法你就可以使用new操作符来创建并实例化一个类。

    Knowledge Prepare - 知识准备
    在JavaScript中, 当你定义了一个新的函数, 你实际上声明了一个新的类, 而这个函数本身就相当于类的构造函数。 下面的代码向你展示了两种不同的方式来创建一个新的Person类, 而Person.prototype的定义也紧跟在函数定义之后。
    var Person = function(name) { // 一个匿名函数, 并将这个函数赋值给一个Person变量, 此时Person成为一个类
    
            this.name = name;
    
    }
    
    function Person(name) { // 直接定义一个叫做Person的函数表示Person类
    
            this.name = name;
    
    }
    
    Person.prototype = { // 定义Person的prototype域
    
            printName: function() {   // 定义一个print函数
    
                   alert(this.name);
    
            }
    
    }

    当你通过函数的方式声明了一个类之后 你就可以通过 new 操作符来实例化这个类。这样 你就可以调用类的成员函数来完成你的逻辑。
    var person = new Person("Joe Smith"); // 使用new操作符来新建一个Person的实例, 并赋给变量person
    
    person.printName(); // person就可以看作是一个实例的引用(reference), 所以可以通过这个引用来调用Person类中的成员函数

    我们来总结一下创建一个新的类的实例的整个流程和步骤:

    1. 通过定义一个函数的方式(匿名或者实名)来声明一个新的类
    2. 
    如果有必要定义这个新的类的prototype
    3. 
    使用new操作符紧跟你所定义的函数来创建一个新的类的实例一旦JavaScript编译器碰到了new操作符它实际上创建了一个空的类实例变量.
    4. 
    将所有这个类的prototype域中的属性与方法复制到这个新的实例中并将其成员函数中所有的this指针指向这个新创建的实例
    5. 
    接下来执行紧跟在new操作符后面的那个函数
    6. 
    当你执行这个函数时如果你试图对一个不存在的属性进行赋值, JavaScript编译器将自动为你在这个实例范围内新创建这个属性
    7. 
    函数执行完毕后将这个初始化完成的实例返回.

    Prototype使用Class对象你可以以一个比较简单的方式来声明一个新的对象。通过使用Class.create(), prototype为你创建了一个默认的构造函数initialize(), 一旦你实现这一函数就可以以一个类似Java中构造函数的方式来创建一个新的类的实例。

    Source View - 源码解析

    var Class = { // 全局静态类, 用于声明一个新的类并提供构造函数支持
    
     create: function() {   
    
        return function() { // 返回一个函数, 代表着这个新声明的类的构造函数
    
          // 一个命名为initialize的函数将被这个类实现作为类的构造函数
    
          this.initialize.apply(this, arguments);// initialize函数将在你实例化一个变量的时候被调用执行(即上面7个步骤中的第5步)
    
        }
    
     }
    
    }

    Field & Function Reference - 属性方法一览
    Class ( 静态 )
    Method / Property
    KindArgumentsDescription
    create()静态方法 /用于声明一个新的类并提供了一个名为initialize构造函数支持
    Analysis & Usage - 分析与使用
    通过Class类, 你可以很容易地使用构造函数的方式创建一个新的类, 这对于Java程序员来说或许更加容易被接受。下面我们列出了Java和JavaScript各自声明和创建一个新的类的代码对比, 我们可以看到, 他们是如此相似:
    var Person = Class.create(); // 类的声明              |public class Person { // 类的声明
    
    Person.prototype = {                                 |    private String name;
    
       initialize: function(name) { // 构造函数          |    public Person(String name){ // 构造函数
    
         this.name = name;                               |       this.name = name;
    
       }                                                 |    }
    
       printName: function() { // 成员函数               |    public void printName(){ // 成员函数
    
         alert(this.name);                               |       System.out.println(name);
    
       }                                                 |    }
    
    }                                                    |}
    
    var person = new Person("Joe Smith");// 创建实例      |Person person = new Person("Joe Smith");// 创建实例
    
    person.printName(); // 函数调用                       |person.printName(); // 函数调用

    展开全文
  • C++用new和不用new创建类对象区别

    万次阅读 2014-08-13 12:10:55
    new创建类对象使用完后需使用delete删除,跟申请内存类似。所以,new有时候又不太适合,比如在频繁调用场合,使用局部new类对象就不是个好选择,使用全局类对象或一个经过初始化的全局类指针似

    起初刚学C++时,很不习惯用new,后来看老外的程序,发现几乎都是使用new,想一想区别也不是太大,但是在大一点的项目设计中,有时候不使用new的确会带来很多问题。

    当然这都是跟new的用法有关的。new创建类对象,使用完后需使用delete删除,跟申请内存类似。所以,new有时候又不太适合,比如在频繁调用场合,使用局部new类对象就不是个好选择,使用全局类对象或一个经过初始化的全局类指针似乎更加高效。

    一、new创建类对象与不new区别

    下面是自己总结的一些关于new创建类对象特点:

    • new创建类对象需要指针接收,一处初始化,多处使用
    • new创建类对象使用完需delete销毁
    • new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间
    • new对象指针用途广泛,比如作为函数返回值、函数参数等
    • 频繁调用场合并不适合new,就像new申请和释放内存一样

    二、new创建类对象实例

    1、new创建类对象例子:

    CTest* pTest = new CTest();

    delete pTest;

    pTest用来接收类对象指针。

    不用new,直接使用类定义申明:

    CTest mTest;

    此种创建方式,使用完后不需要手动释放,该类析构函数会自动执行。而new申请的对象,则只有调用到delete时再会执行析构函数,如果程序退出而没有执行delete则会造成内存泄漏。

    2、只定义类指针

    这跟不用new申明对象有很大区别,类指针可以先行定义,但类指针只是个通用指针,在new之前并为该类对象分配任何内存空间。比如:

    CTest* pTest = NULL;

    但使用普通方式创建的类对象,在创建之初就已经分配了内存空间。而类指针,如果未经过对象初始化,则不需要delete释放。

    3、new对象指针作为函数参数和返回值

    下面是天缘随手写一个例子,不太严谨。主要示意一下类指针对象作为返回值和参数使用。

     

    示例:

    类的内存分配简单总结,代码片段如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    #include <iostream>
    using namespace std;
     
    /**
    * yanggang
    * http://blog.ithomer.net
    * 2014-08-11
    **/
     
     
    class ClassA {
         private :
             int A;
             int B;
     
         void prin1() {
          }
     
         void prin2() {
         }
     
         virtual void prin3() {
         }
    };
     
    class ClassB : public ClassA {
         public :
             int C;
             int D;
     
         void prin4() {
         }
     
         void prin5() {
         }
     
         virtual  void  prin6() {
         }
    };
     
    int main( int argc, char * argv[]) {
         cout<< sizeof (ClassA)<<endl;        // 16
         cout<< sizeof (ClassB)<<endl;        // 24
     
         return 0;
    }

    测试环境:

    Ubuntu 12.04.5 LTS   x86_64 GNU/Linux

    g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 编译参数 -m64 

    结果是

    homer@homer-pc:~/Desktop$ g++ testMem.c -o testMem && ./testMem
    16
    24

    结果为什么是这样?

    32位系统int4个字节,64位系统int也占4个字节(不是8个字节),而一个类中所有的虚函数通过一个虚函数指针管理,类对象的大小只包含这个vptr指针(在64位机器上指针sizeof为8个字节),其他虚函数是放在别的内存空间中管理,vptr指针在64位机器上是8个字节大小(32位机器上是4个字节)。注意到普通成员函数并不占类对象的大小空间,因为普通成员函数通过this指针管理,一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。

    sizeof(ClassA)

    1)int A 和 int B 各占4个字节,考虑64位机器编译器对其规则,合并为8个字节

    2)virtual void prin3() 虚函数的vptr指针,在64位机器编译器上占8个字节

    3)合计 sizeof(ClassA)为 8 + 8 = 16个字节

    this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。这个this指针会因编译器不同而有不同的放置位置可能是栈,也可能是寄存器,甚至全局变量。

    子类其实不管如何继承,用sizeof()算该类的大小都会把父类中的私有成员变量所占的空间算进去,也就是说,私有变量也在子类中分配了内存,但你却不可以直接访问,这起到一个保护作用,这如同一个珠宝,共有继承就是开放性的展览,而私有继承是把珠宝锁起来,你却不能动,要动珠宝如果有管家(基类的public中定义了一些对其私有变量操作的成员函数,)只能让管家帮你代劳。

    sizeof(ClassB)

    1)int A 和 int B 各占4个字节,是父类ClassA中的私有变量,合并占用8个字节

    2)virtual void prin3() 虚函数的vptr指针,父类ClassA在子类中不会分配空间

    3)int C 和 int D 各占4个字节,在子类中会分配空间,合并占用8个字节

    4)virtual void prin6() 虚函数的vptr指针,在64位机器编译器上占8个字节

    5)合计 sizeof(ClassB)为 8 + 8 + 8 = 24个字节

    注明: 上述示例在32位编译器上测试,sizeof(ClassA)和sizeof(ClassB)分别为12和20字节(虚函数指针占用空间少了4字节)


    只有虚函数会占用一个指针大小的内存,原因是系统用一个指针维护这个类的虚函数表,并且注意这个虚函数无论含有多少项(类中含有多个虚函数)都不会影响类的大小。

     

    知识延伸:

    1) 空 ClassA(验证空Class占用空间大小

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class ClassA {
         private :
     
         void prin1() {
          }
     
         void prin2() {
         }
    };
     
    cout<< sizeof (ClassA)<<endl;        // 1

     

    2) ClassA 只有一个char(验证编译器对其规则

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class ClassA {
         private :
             char C;
     
         void prin1() {
          }
     
         void prin2() {
         }
    };
     
    cout<< sizeof (ClassA)<<endl;        // 1

     

    3)ClassA 有一个char和一个虚函数(或一个long型)(验证编译器对其规则二

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class ClassA {
         private :
             char C;
     
         void prin1() {
          }
     
         void prin2() {
         }
     
         virtual void prin3() {
         }
    };
     
    cout<< sizeof (ClassA)<<endl;        // 16

     

    4)ClassA 有一个char和一个虚函数(或一个long型),且对调char和虚函数的先后顺序(验证编译器对其规则三

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class ClassA {
     
         void prin1() {
          }
     
         void prin2() {
         }
     
         virtual void prin3() {
         }
     
         private :
             char C;
    };
     
    cout<< sizeof (ClassA)<<endl;        // 16

     

    5)ClassA 有一个char,一个int,一个虚函数(或一个long型)(验证编译器对其规则四

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class ClassA {
         private :
             char C;
             int A;
     
         void prin1() {
          }
     
         void prin2() {
         }
     
         virtual void prin3() {
         }
    };
     
    cout<< sizeof (ClassA)<<endl;        // 16

     

    6)ClassA 有一个char,一个int(验证编译器对其规则五

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class ClassA {
         private :
             char C;
             int A;
     
         void prin1() {
          }
     
         void prin2() {
         }
    };
     
    cout<< sizeof (ClassA)<<endl;        // 8

     

    7)ClassA 只有一个int(验证编译器对其规则六

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class ClassA {
         private :
             int A;
     
         void prin1() {
          }
     
         void prin2() {
         }
    };
     
    cout<< sizeof (ClassA)<<endl;        // 4

     

    总结如下:

    1) 空类的 sizeof 为1个字节

    2) 只有一个char的类,sizeof为一个字节

    3) 类中含有char和虚函数,将以最大的变量或指针为编译器对齐规则,例如:虚函数指针占8个字节(64位编译器),则char虽然只占1个字节,但对齐后空余了7个字节,合并类占8(指针) + 1(char) + 7(对齐的空字节) = 16个字节

    4) 对齐规则,跟变量或虚函数的先后顺序无关,只跟最大变量类型或函数指针有关,函数指针跟编译器最大对齐位数有关(不太好理解,请继续往下看)

    5) char和int合占8个字节,虚函数指针占8个字节,且以最大的虚函数指针的8字节对其,其中char占一个空余3个字节合并占4个,int占4个字节,按8位规则对齐,合计16字节

    6) 一个char和int合并占8个字节,无虚函数,此时以最大变量类型int对齐,因此char占1字节空3字节占4字节

    7)一个int占4位,自己便是最大的对齐规则; 2)一个char同理也占1个字节,此处跟编译器最大64位对齐规则无关(即一个int或一个char,不会拓展到占用8字节)

     

    这里,又延伸出了一个很有意思的问题,空类sizeof为什么不为0,而为1?

    回答这个问题,需要回到编译器和类的实例化问题上来,在学校看过《深度探索C++对象模型》,类分抽象类和普通类,空类属于普通类,是可以被实例化的。

    每个类的实例,在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址,因此1)中的空类ClassA默认会占用1个字节。


    原文地址:http://blog.ithomer.net/2014/08/c-class-object-created-with-the-new-and-not-new-distinction/

    展开全文
  • 对象、定义创建对象

    千次阅读 2018-07-09 19:35:00
    对象对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类类就相当于制造飞机时的图纸,用它来进行创建的飞机就相当于对象1. 人以类聚 ...
  • 内部类对象创建

    千次阅读 2019-07-04 09:46:18
    创建外部类对象,之后外部类对象调用new关键字创建内部类对象。 Outter outter=new Outter(); Outter.Inner inner=outter.new Inner(); 静态内部类对象创建:外部类.内部类直接创建。...
  • new一个类对象使用类名创建一个对象有什么区别? 用new来给一个类的对象分配空间,和使用类名称来定义一个类的对象,有什么区别?难道区别只是new的返回值是个指针,而对象定义得到的是变量名么?或者是在存储...
  • 在C++里,有两种方法创建对象: 方法一: ClassName object(param); 这样就声明了一个ClassName类型的object对象,C++会为它分配足够的存放对象所有成员的存储空间。 注意:为节省存储空间,C++创建
  • 创建派生类对象,构造函数的执行顺序

    万次阅读 多人点赞 2019-04-24 22:04:10
    创建派生类对象,构造函数的执行顺序() 正确答案: A A 基类构造函数,派生类对象成员构造函数,派生类本身的构造函数 B 派生类本身的构造函数,基类构造函数,对象成员构造函数 C 基类构造函数,派生类...
  • Python中的的定义和对象创建

    万次阅读 多人点赞 2018-08-16 17:35:59
    面向对象中两个重要的概念: 1.类 :对一类事物的描述,是抽象的、概念上的定义。...1.创建类和创建类对象 1.创建类,类主要由类名,属性,方法组成,当然创建一个类时,属性和方法可以选择的。 cla...
  • C# 创建类对象数组

    万次阅读 2019-02-12 22:52:32
    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;...namespace _0606_创建类对象数组 { class Program { static void Main(string...
  • new创建类对象使用完后需使用delete删除,跟申请内存类似。所以,new有时候又不太适合,比如在频繁调用场合,使用局部new类对象就不是个好选择,使用全局类对象或一个经过初始化的全局类指针似乎更加高
  • c++创建类对象3种方法

    千次阅读 2017-08-15 14:55:41
    创建对象方式注意:==是堆还是栈,创建方式== http://blog.csdn.net/azhexg/article/details/14225545 #include <iostream> using namespace std; class A { private: int n; public: A(int m):n(m) { ...
  • java中创建类对象的各种方法

    千次阅读 2018-01-18 00:15:50
    最近听朋友提起面试题的时候,在加上整理复习汇总java基础知识,刚好写下来记录创建java对象的方法,又称为java的实例化,有很多种,列举如下:一、使用Spring管理创建学过Spring框架的同学都知道,我们可以利用...
  • C++用new和不用new创建类对象的区别

    千次阅读 2015-06-24 15:57:04
    new创建类对象使用完后需使用delete删除,跟申请内存类似。所以,new有时候又不太适合,比如在频繁调用场合,使用局部new类对象就不是个好选择,使用全局类对象或一个经过初始化的全局类指针似乎更加高
  • Python 创建类对象实例的过程

    万次阅读 2018-04-20 16:19:35
    1、问题由来 有一次在的定义时将一个方法外的属性前加上了selfclass Myclass(object): self.test='hello' #错误使用self def __init__(self, x): self.x = x c1 = Myclass(11) 运行时报错:Traceback (most...
  • new创建类对象使用完后需使用delete删除,跟申请内存类似。所以,new有时候又不太适合,比如在频繁调用场合,使用局部new类对象就不是个好选择,使用全局类对象或一个经过初始化的全局类指针似
  • 如何根据字符串动态创建类对象

    万次阅读 2011-07-09 14:38:25
    如何根据字符串动态创建类对象 今天跟同事聊天的时候,同事有一个需求,就是如何根据类的名字和值,动态返回该类的实例对象。比如,我们给一个函数传入字符串类名”java.lang.String”和值“wuguowei”,则该函数则...
  • Java抽象不能创建对象

    万次阅读 2017-03-06 14:35:21
    抽象和接口都能创建对象,只是后边的new不能是new他们自己,但可以new他们的实现(必须是,不能是抽象和接口), 人们使用抽象和接口只是为了说明要干什么事,而让他们的实现去根据自己的需要去实现这些...
  • 创建对象使用对象——谈谈工厂的作用

    万次阅读 多人点赞 2012-04-30 01:54:54
    在设计模式的教学和推广过程中,很多企业学员和在校学生经常问... 与一个对象相关的职责通常有三对象本身所具有的职责、创建对象的职责和使用对象的职责。对象本身的职责比较容易理解,就是对象自身所具有的一些数
  • 抽象创建对象吗?

    千次阅读 2020-07-15 00:27:20
    抽象是不能创建对象的原因: 1.子类更具体,父类更抽象,直接创建父类对象本身没有意义。 2.如果创建的是父类对象再调用方法的时候,调用的父类中的方法,而非子类的方法,它违背了多态的这种思想和设计 3.因为...
  • 使用对象字面量创建对象

    千次阅读 2016-08-14 16:03:45
    今天在学习《js高程》时看到了使用对象字面量创建对象的表示法,了解到对象字面变量是对象定义的一种简写形式,目的在于简化创建包含大量属性的对象的过程,举一个简单的例子var person = {name : "tom",age : 21};...
  • java使用反射创建对象

    万次阅读 2016-10-08 17:12:41
    Class对象中包括构造器(Constructor)、属性(Field)、方法(Method)。...这个方法是使用Class对象对应的默认构造器创建对象,这就要求Class对象对应必须要有默认构造器。 2、使用Class对象获取指定
  • scala不使用new关键字创建对象实例

    千次阅读 2017-07-17 22:23:41
    在scala中,scala不使用new关键字创建对象实例,一般有2中方法: 1. 为类创建伴生对象,并在伴生对象内按照所需的构造函数签名定义一个apply方法; 2.将定义为case。 1)用apply方法创建一个伴生对象: ...
  • 如何定义创建对象

    千次阅读 2018-11-05 16:40:43
    【10】定义和对象创建 ,定义了一个功能模块。 10-1 成员变量:描述对象的属性。 10-2 成员方法:描述对象的行为。 package bike; /* * 定义和对象创建 */ public class bike { String color="蓝色&...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,024,416
精华内容 1,209,766
关键字:

创建类的对象使用