精华内容
下载资源
问答
  • 这道题的思路是,我只让这个通过一个公有函数实例化对象,即可以将构造函数设置为私有成员函数。include using namespace std;class Single { public: static Single& SingleCreate() { if (m == NULL) { m =...

    其实这是一道面试题。
    这道题的思路是,我只让这个类通过一个公有函数实例化对象,即可以将构造函数设置为私有成员函数。

    include <iostream>
    using namespace std;
    
    class Single
    {
    public:
    
        static Single& SingleCreate()
        {
            if (m == NULL)
            {
                m = new Single();
            }
                return *m;
        }
        ~Single()
        {
            delete m;
        }
    
        Single(const Single &a)
        {
        if (m == NULL)
        {
        m = new Single();
        }
        }
    
    private:
        Single()
        {}
        static  Single *m;
    };
    
    Single* Single::m = NULL;
    
    int main()
    {
        Single a = Single::SingleCreate();
    }

    这是我第一次写出的代码,我本来认为这样就可以了,结果经过我的调试,发现这样写是有问题的。
    这里写图片描述

    通过上面的图片可以看出,我们实例化的a的地址,跟在SingleCreate函数中返回的m的值是不同的,即这个类实例化了两个对象,这样就偏题了。
    经过分析,我们现在来看SingleCreate函数

        static Single& SingleCreate()
        {
            if (m == NULL)
            {
                m = new Single();
            }
                return *m;
        }

    这里retuen 的*m,会自动生成拷贝构造函数,因为return *m是返回一个对象,这里是返回临时变量,自动调用拷贝构造函数,因为我们没有定义拷贝构造函数,所以这里会自动生成一个拷贝构造函数。
    所以达不到只实例化一个对象的目的
    经过上面的分析,经代码优化为

    
    class Single
    {
    public:
    
    
        static Single* SingleCreatePtr()
        {
            if (m == NULL)
            {
                m = new Single();
            }
            return m;
        }
        ~Single()
        {
            delete m;
        }
    
    
    private:
        Single()
        {}
    
        static  Single *m;
    };
    Single* Single::m = NULL;
    int main()
    {
        Single *a = Single::SingleCreatePtr();
    }

    这个时候经过调试,得到下面
    这里写图片描述
    这个时候就得到的是一个对象。因为传指针的实质是在传地址,不会产生临时变量。
    现在已经解决了在返回值时只实例化一个对象的问题
    接下来看第三个问题
    三、构造函数
    接下来我们在main函数中加这么一句话:

    Single *b = a;

    这个时候会发生什么呢?
    对,会实例化出另一个对象,这是因为编译器自动生成了赋值构造函数,就像上面的拷贝构造函数一样,都是编译器自动生成并调用的,那么如何防止这些情况的发生?
    我的方法是在类中只声明不定义拷贝构造函数以及赋值构造函数。

    class Single
    {
    public:
    
        static Single& SingleCreate()
        {
            if (m == NULL)
            {
                m = new Single();
            }
                return *m;
        }
        static Single* SingleCreatePtr()
        {
            if (m == NULL)
            {
                m = new Single();
            }
            return m;
        }
        ~Single()
        {
            delete m;
        }
    
    
    private:
        Single()
        {}
        Single(const Single &a);
        Single& operator = (const Single &a);
        static  Single *m;
    };

    即将拷贝构造函数和赋值运算符重载函数都变成私有的成员函数,在外不可调用,就避免了因为构造函数多实例化对象的情况。
    四、通过静态局部变量

    class Single  
    {  
    private:  
        Single()   //构造函数是私有的  
        {  
        }  
    public:  
        static Single & GetInstance()  
        {  
            static Single instance;   //局部静态变量  
            return instance;  
        }  
    };  
    

    静态局部变量在GetInstance函数中被定义,初始化为0,且静态局部变量存放在内存的全局数据区。函数结束时,静态局部变量不会消失,每次该函数调用 时,也不会为其重新分配空间。它始终驻留在全局数据区,直到程序运行结束。静态局部变量的初始化与全局变量类似.如果不为其显式初始化,则C++自动为其 初始化为0。
    静态局部变量与全局变量共享全局数据区,但静态局部变量只在定义它的函数中可见。
    通过声明静态局部变量,但不进行初始化及赋值,那么编译器自动初始化为0,且永远不会改变,所以只会实例化一个对象。这个方法更加便捷高效。
    但是上面的代码没有考虑类拷贝的问题,大家参照上面的类拷贝问题可以自己把函数加上,然后去试一试,有问题可以留言大家一起解决~

    展开全文
  • 一个类只实例化一个对象称为单例模式

    一个类只实例化出一个对象称为单例模式

    #include <iostream>
    
    class SingleClass
    {
    public:
        static SingleClass* GetSingleClass()    //静态成员函数
        {
            if (Count > 0)
            //如果Count大于0,那么就调用new创建一个类指针,并且计数Count减1,否则返回NULL
            {
                Count--;
                return new SingleClass();
            }
            else
            {
                return NULL;
            }
        }
    private:
        SingleClass(){};
        static int Count;   //静态成员变量Count,不允许在类中初始化。定义为const则可以在这初始化,但是不可更改,不适合在这使用
    };
    
    int SingleClass::Count = 1; //Count的初始化,可以自己设置限制创建实例的个数
    
    int main()
    {
        SingleClass* test;  //只能通过定义类指针来创建类实例
        test = SingleClass::GetSingleClass();
        return 0;
    }

    #include <iostream>
    
    class SingleClass
    {
    public:
        static SingleClass* GetSingleClass()    //静态成员函数
        {
            if (pSinClass == NULL)
            //如果pSinClass为NULL,那么就调用new创建一个类指针,否则返回NULL
            {
                pSinClass = new SingleClass();
                return pSinClass;
            }
            else
            {
                return NULL;
            }
        }
    private:
        SingleClass(){};
        static SingleClass* pSinClass;   //静态成员变量pSinClass,不允许在类中初始化。定义为const则可以在这初始化,但是不可更改,不适合在这使用
    };
    
    SingleClass* SingleClass::pSinClass = NULL; //pSinClass的初始化
    
    int main()
    {
        SingleClass* test;  //只能通过定义类指针来创建类实例
        test = SingleClass::GetSingleClass();
        return 0;
    }



    展开全文
  • 3.2、抽象一个类实例化对象

    千次阅读 2018-03-28 19:20:36
    一、抽象一个类 二、实例化对象 1、实例化对象 2、对象类型在内存中分配情况 三、$this 四、构造函数和析构函数

    一、抽象一个类
    所谓抽象一个类,就是怎么创建一个类。
    1、类的声明
    类的声明只需要使用关键字class,有时候需要在关键字前加上修饰类的关键字,如abstract或者final等,有时候还有Trait等关键字来取代class。声明格式如下:
    【修饰类的关键字】class 类名{
    类中成员
    }
    实例:eg:

    <?php
    class Base {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    

    类名、变量名、函数名的命名规则,需要遵循PHP自定义名称的命名规则。如果由多个单词组成,习惯上每个单词的首字母要大写。
    2、类的成员属性
    类的成员属性声明,需要public,protected,private,static等关键字来修饰
    eg:

    <?php 
    
    class test 
    { 
        public $var1 = 1; 
        protected $var2 = 2; 
        private $var3 = 3; 
        static $var4 = 4; 
    } 
    

    3、类的成员方法
    类的成员方法声明和其属性类似,只是要加关键字function,也要有关键修饰词:public,protected 和 private等。
    eg:

    <?php
    class MyClass
    {
        private $foo = FALSE;
    
        public function __construct()
        {
            $this->$foo = TRUE;
    
            echo($this->$foo);
        }
    }
    

    二、实例化对象
    我们在创建类之后,并不是直接使用类,而是通过类来实例化出对象。
    1、实例化对象
    实例化对象需要使用的new关键字,一个类可以被实例化出多个对象,对象之间没有关联。
    eg:

    <?php
    	class MyClass
    	{
    	    private $foo = FALSE;
    	
    	    public function __construct()
    	    {
    	        $this->foo = TRUE;
    	
    	        echo($this->foo);
    	    }
    	}
    	
    	$bar = new MyClass();
    

    2、对象类型在内存中分配情况
    内存大体上被分为四段:
    1)栈空间段
    该空间段主要特点是:空间小,被访问速度快,后进先出(先进后出)。用于存储占用空间不变且占用空间小的数据类型的内存段。例如整型1、10、10000在内存中占用的空间是等长的,都是32位4字节。整型、double、boolean等类型都可以存储在栈空间段。
    2)堆空间段
    用于存储数据长度不定长,而且占用空间很大的数据类型的数据,例如字符串、数组、对象。该段是动态分配的。
    3)初始化数据段
    用于存放可执行文件中已初始化的全局变量,数据段存储经过初始化的全局和静态变量
    4)代码段
    存放可执行文件的操作指令,就是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只允许读取操作,不允许写入(修改)操作。例如程序中的函数就存储在该内存段中。
    其各段特点简要说明如下图:
    这里写图片描述

    实例说明:eg:

    <?php
    	class person{
    		public $name;
    		public $sex;
    		public function say(){
    			echo '666';
    		}
    	}
    	$p1 = new person();
    	$p2 = new person();
    	$p3 = new person();
    	/**$p1是第一个对象的引用变量(通过“=”把第一个对象的首地址"0xff001",赋值给了$p1),
    	 * 存放的是一个十六进制的整数被存放在栈内存中。相当于一个指针指向堆里边的对象。
    	 * 所以访问对象里边的成员都需要通过引用变量$p1
    	 */
    

    上段代码图形说明如下:
    这里写图片描述
    易混淆点:
    1、当将对象赋值给另一个变量时,此时是将对象的“首地址”赋值给了另一个变量,堆内的对象并没有复制一份。
    实例说明eg1:

    <?php
    	class test{
    		public $name;
    	}
    	$a = new test();
    	$b = $a;//这里与$b = &$a效果是一样的,仅针对对象
    	$b->name = 123;
    	var_dump($a->name);//输出123,说明只是将第一个对象的“首地址”赋值给了$b,改变的都是一个堆内的对象属性值
    	unset($a);
    	var_dump($b->name);//输出123,unset释放的只是第一个对象栈中的引用变量。
    	
    

    示例1说明图:
    这里写图片描述
    2、如果想得到一个对象的副本,用$a =clone $b; 用了clone后会产生一个新对象,分配内存,独立于原来的$a。
    eg2:

    <?php
    	class test{
    		public $name;
    	}
    	$a = new test();
    	$b = clone $a;
    	$b->name = 123;
    	var_dump($a->name);//输出null
    	unset($a);
    	var_dump($b->name);//输出123
    

    示例2图形说明:
    这里写图片描述

    3、当一个对象的引用断了的时候,这个对象在堆中就被当做垃圾,php就会执行垃圾回收机制,将这个对象回收,如图
    这里写图片描述
    4、栈内后进先出(先进后出)机制
    eg3:

    <?php
    class test  
    {  
        public $name;  
        //构造函数,当类被实例化时,会自动执行
        public function __construct($name)  
        { 
            $this -> name = $name;  
            echo $this->name."这里被执行了<br>";  
        }  
        public function __destruct()  
        {  
            echo $this->name."我被回收了<br>";  
        }  
    }
    $p1 = new test('王二');
    $p1 = 1;  
    $p2 = new test("张三");  
    $p3 = new test("李四");  
    /**输出 
     * 王二这里被执行了
     * 王二我被回收了
     * 张三这里被执行了 
     * 李四这里被执行了 
     * 李四我被回收了 
     * 张三我被回收了 
     */
    //因为$p1引用被重新赋值,最先失去了引用,所以调用了析构函数。
    //然后在这个脚本执行完成后,开始自动调调用后边对象的析构函数,
    //因为$p2,$p3引用存储在栈内,因为栈内后进先出机制,最后创建的对象最先被释放,所以$p3先被销毁。
    

    三、$this
    在对象的内部,在对象的成员方法中访问自己对象的成员属性,或者对象内的其他成员方法,可以用特殊对象应用this。一旦我们new了一个对象,那么对象中的每个成员方法中都存在一个特殊的对象应用‘this。 一旦我们new了一个对象,那么对象中的每个成员方法中都存在一个特殊的对象应用`thisnewthis。成员方法属于那个对象,那么$this就代表哪个对象。就像你别人要访问你的性别,要用“张三是男生”,但是你自己访问自己的性别,你要用“我是男生”一样。eg3中的例子就用到了$this`。

    四、构造函数和析构函数
    1、构造函数__construct ([ mixed $args [, $... ]] )
    具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。
    注意:
    如果子类中定义了构造函数则不会调用其父类的构造函数。
    要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()。
    如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继承(假如没有被定义为 private 的话)。

    eg1:

    <?php
    class Base {
       function __construct() {
           print "1";
       }
    }
    
    class Sub extends Base {
       function __construct() {
           parent::__construct();
           print "2";
       }
    }
    
    class OtherSub1 extends Base {
       function __construct() {
           print "2";
       }
    }
    
    class OtherSub2 extends Base {
       
    }
    
    $obj = new Base();//输出1
    $obj = new Sub();//输出12
    $obj = new OtherSub1();//输出2
    $obj = new OtherSub2();//输出1
    

    附:构造函数的参数
    eg:

    <?php
    	class Base {
    		public $name;
    		public function __construct($name = '小王') {
    		   $this->name = $name;
    		}
    		
    		public function name(){
    			echo $this->name;
    		}
    	}
    	$name1 = new Base('小李');
    	$name1->name();//输出‘小李’
    	$name2 = new Base();
    	$name2->name();//输出‘小王’
    

    2、析构函数__destruct ( void )
    析构函数并是不销毁什么,而是会在到某个对象的所有引用都被删除或者当对象被销毁时执行。
    注意
    析构函数没有参数,
    和构造函数一样,父类的析构函数不会被子类中调用,
    要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。
    此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类的。
    析构函数即使在使用 exit() 终止脚本运行时也会被调用。在析构函数中调用 exit() 将会中止其余对象的所有引用都被删除或者当对象被销毁的析构函数的执行。这一点,可以通过实例细细体会。

    展开全文
  • java实例化一个抽象对象

    千次阅读 2019-07-16 16:23:09
    不对啊,根据我的知识一个抽象不能直接实例化一个对象出来,面向对象期末考试的卷子还有专门一道你改错的题,一般抽象直接实例化对象都是每年必考的错误点。那这个对象从哪实例化,国家分配的吗?先不管,结果...

    问题的起因

    今天学习接口,继承和多态这一部分,遇到一个练习题挺好玩的。题目要求,创建一个抽象类,然后去实例化一个抽象类的对象。

    不对啊,根据我的知识一个抽象类不能直接实例化一个对象出来,面向对象期末考试的卷子还有专门一道让你改错的题,一般抽象类直接实例化对象都是每年必考的错误点。那这个对象从哪实例化,国家分配的吗?先不管,结果随手一new就见error

    分析

    单身狗开始做梦,假如我已经有了对象,那到时候是不是可以跟着对象一起去见从未谋面的家长了呢?想到这流下了没有实力的泪水,等等,对啊,假如我有了一个已经实例化的对象,而这个对象又是继承自一个抽象类,实例化对象之前肯定会先实例化父类的,那不就可以实例化抽象类了。想到这马上放弃撩妹,开始撸代码

    代码

    只要想法想到了,代码其实很简单

    //创建一个抽象类,实例化一个抽象类的对象
    abstract class B  //创建抽象类B
    {
    	private String str;//私有成员变量str
    	
    	public B(String a)//抽象类的构造函数
    	{
    		System.out.println("父类的实例化");
    		this.str=a;
    		System.out.println(str);
    	}
    	
    	public abstract void play();//抽象类中的play()抽象方法
    
    }
    
    
    public class A extends B  //A类继承抽象类B
    {
    	public A(String a)//A的构造函数
    	{
    		super(a);
    		System.out.println("子类的实例化");
    	}
    	
    	@Override  //覆盖父类B中的play()
    	public void play()
    	{
    		System.out.println("重写抽象类中的play()方法");
    	}
    	
    	public static void main(String[] args)
    	{
    		B b=new A("小杰杰要加油啦"); //实例化抽象类对象
    	}
    }
    

    结果

    在这里插入图片描述
    单身狗也只能自己创建对象给自己加油了,继续去构造对象啦

    展开全文
  • C++只能实例化一个对象

    千次阅读 2015-10-18 18:07:54
    # include # include using namespace std;1.创建class Student { public: static Student* Limit(); //静态成员函数 void display(); private: static Student *total; //静态数据成员指针
  • C#实例化一个对象的方法

    千次阅读 2017-06-29 21:31:39
    实例化一个对象  类名 对象名=new 类名() Teacher t= new Teacher();
  • 实例化一个对象(加载)的执行顺序详解这篇博客将以加载执行顺序为探索的起点,串讲涉及到的Java相关知识,主要是这个流程中JVN内部运行机制的解析。结论Created with Raphaël 2.1.0开始父类静态代码子类静态代码...
  • 深入理解Java对象的创建过程:的初始化与实例化

    万次阅读 多人点赞 2017-05-18 14:17:45
    实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用构造器完成的初始化。在初始化过程中或初始化完毕后,根据具体情况才会去对进行实例化。本文试图对JVM...
  • java 利用反射实例化类对象

    千次阅读 2014-10-04 10:06:22
    * java 使用反射实例化一个类对象 * 第一种方式:创建类类对象,调用类类对象的newInatance方法获取要实例化对象,然后调用对象的setter方法设置属性。 * 第二种方式:使用类类对象的getConatructor方法...
  • C++实例化对象

    千次阅读 2018-09-02 18:47:11
    C语言使用函数对内容进行封装的,而C++是用进行封装的 ...在创建实例化对象时,本身并不被分配空间 对象包括里的成员变量 若计算的大小,需计算成员变量大小之和,但要注意内存对齐 空大小为一个...
  • 用SolidBrush实例化对象selectedcolor时,括号里打?号,我是第头见。如下面的代码,或者图片中黄色箭号所指。视频教程里没有详解这功能。有大侠愿意赐教么? [img=...
  • Java中子中子类实例化父类对象

    千次阅读 2019-05-03 18:08:39
    一个父类,里面有两个方法,doing ()和talking(),并在doing ()方法中调用talking()方法。代码如下: public class Father { public void doing (){ talking(); } public void talking(){ ...
  • 使用Class 实例化一个对象

    千次阅读 2011-02-16 14:26:00
    <br />使用Class对象调用newInstance()实例化一个className对象时,className必须有无参数的构造方法 import java.lang.reflect.*;   class Rect { double width,height,area;...
  • 一个类实例化对象所占空间的大小? 注意不要说的大小,是的对象的大小. 首先,的大小是什么?确切的说,只是一个类型定义,它是没有大小可言的。 用sizeof运算符对一个类型名操作,得到的是具有该类型实体...
  • 关于接口实例化一个对象

    千次阅读 2014-04-18 20:42:07
    IList IList11  ...只是想创建一个基于接口IList的对象实例,只是这个接口的方法是由List实现的。所以它只是希望使用到List 实现了IList接口的那些方法,非IList的方法, IList11 就用不到了。 
  • Book book=new Book(); System.out.println(book); 输出一个Book 的引用地址。 怎么不通过对象属性判断这个对象为不为空?
  • Java使用new和反射实例化内部类对象

    千次阅读 2017-03-07 16:09:25
    java使用new和反射实例化内部类对象 前两天看到一道面试题,是关于内部的知识,觉得很有意思,现对其详细讲解,绝对原创!~ 这道题是这样的: 根据注释填写(1),(2),(3)处的代码 public class Test{ public ...
  • 今天我在实例化一个类是编译器报以下错误: No enclosing instance of type Person is accessible. Must qualify the allocation with an enclosing instance of type Person (e.g. x.new A() where x is an ...
  • java实例化对象

    千次阅读 2016-05-15 08:35:19
    摘要:分享牛,分享牛分享,java加载机制,java实例化对象,java实例化对象机制,java基础。java是如何实例化对象的呢?以及实例化对象的先后顺序是什么?下面我们以测试的方式说明.1.1. 声明父类public class A ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,713,250
精华内容 685,300
关键字:

怎么让类只实例化一个对象