-
2019-12-03 13:50:00
抽象类其实是可以被实例化的,但是它的实例化方式并不是通过普通的new方式来创建对象,而是通过父类的应用来指向子类的实例间接地实现父类的实例化,因为子类在实例化之前,一定会先实例化它的父类。这样创建了继承抽象类的子类对象,也就把其父类(抽象类)给实例化了。
注意:接口与抽象类非常类似,但是它不可以被实例化,因为接口压根没有构造函数。
public abstract class B { private String str; public B() { System.out.println("父类已经实例化"); } public B(String a) { this.str = a; System.out.println(str); } public abstract void play(); }
然后,定义一个子类C去继承类B,并实现其中的抽象方法
public class C extends B{ public C(String c){ System.out.println("子类已经被实例化"); } @Override public void play() { System.out.println("我实现了父类的方法"); } public static void main(String[] args){ B c = new C("c"); } }
运行结果如下:
父类已经实例化 子类已经被实例化
更多相关内容 -
子类对象实例化全过程
2022-04-05 11:31:16子类对象实例化全过程 1.概念 从结果上看:(继承性): 子类继承父类以后,就获取了父类中声明的属性或者方法 创建子类的对象,在堆空间中,就回加载所有父类中声明的属性 从过程上来看: 当我们通过子类的... -
【C++】面向对象编程,为什么将父类指针用子类实例化?(code c++)
2021-03-15 09:42:40索引实例化概念定义形式为什么将父类指针用子类实例化?目的——实现多态程序代码实现多态 code c++运行结果结论 实例化概念 定义 实例化是指在面向对象的编程中,把用类创建对象的过程称为实例化。是将一个抽象的...
实例化概念
定义
实例化是指在面向对象的编程中,把用类创建对象的过程称为实例化。是将一个抽象的概念类,具体到该类实物的过程。
形式
实例化过程中一般由类名 *对象名 = new 类名(参数1,参数2…参数n)构成。
为什么将父类指针用子类实例化?
目的——实现多态
这个实例是子类的,但父类声明,所以正常情况下,访问不到子类中非继承自父类的成员;
换句话说,只能访问到子类从父类继承来的 override 成员 + 父类原有的未被该子类 override 成员(第二部分包括所有非 virtual 成员)。
再换一句话说,当前在子类中用 override 重写父类中 virtual 申明的虚方法,此时父类声明对象并通过子类实例化,接着调用该方法,调用的是父类的函数,执行时的是子类中重写的方法。场景如函数传参,形参为父类类型,传入子类,其调用方式相同,而调用的是子类重写后方法,增加了接口通用性。而如果形参为某个子类类型,那么只能传入该子类,多态也就不存在。
(此处推荐了解虚函数表,从 C++ 语言设计的角度出发,探索 C++ 对象模型,加深对 OOP 三大特性之一多态的理解,感受其语言设计哲学的魅力)
程序代码
实现多态 code c++
#include <iostream> #include <ctime> using namespace std; class Animal { public : Animal() = default; Animal(string name) : name(name) {} virtual void run() { cout << "I don't know how to run" << endl; } virtual void getName() final {} void testFunc() { cout << "Animal class" << endl; } virtual void fl1() {} private: string name; }; class Cat : public Animal { public : Cat(string name) : Animal(name) {} void run() override final { cout << "I can run whilth four legs" << endl; } void fl1() override {} }; class People : public Animal { public : People(string name) : Animal(name) {} void run() override { cout << "I can run with two legs" << endl; } }; class Bat : public Animal { public : Bat(string name) : Animal(name) {} void run() override { cout << "I can fly" << endl; } }; int main() { // 建议读者, 去虚函数声明及重载, 再运行程序代码查看结果, 可对实现多态的操作加深理解 #define MAX_N 10 srand(time(0)); Animal **zoo = new Animal*[MAX_N]; for (int i = 0; i < MAX_N; ++i) { switch(rand() % 3) { case 0: zoo[i] = new Cat("cat"); break; case 1: zoo[i] = new People("people"); break; case 2: zoo[i] = new Bat("bat"); break; } } for (int i = 0; i < MAX_N; ++i) { zoo[i]->run(); zoo[i]->testFunc(); cout << "------------" << endl; } return 0; }
运行结果
I can run whilth four legs Animal class ------------ I can run whilth four legs Animal class ------------ I can run whilth four legs Animal class ------------ I can run whilth four legs Animal class ------------ I can run with two legs Animal class ------------ I can run with two legs Animal class ------------ I can run whilth four legs Animal class ------------ I can run whilth four legs Animal class ------------ I can fly Animal class ------------ I can run whilth four legs Animal class ------------
结论
代码示例,有问题留言。
-
详解JAVA对象实例化过程
2020-08-18 10:32:171 对象的实例化过程对象的实例化过程是分成两部分:类的加载初始化,对象的初始化要创建类的对象实例需要先加载并初始化该类,main方法所在的类需要先加载和初始化类初始化就是执行<clinit>方法,对象实例化是...1 对象的实例化过程
- 对象的实例化过程是分成两部分:类的加载初始化,对象的初始化
- 要创建类的对象实例需要先加载并初始化该类,main方法所在的类需要先加载和初始化
- 类初始化就是执行<clinit>方法,对象实例化是执行<init>方法
- 一个子类要初始化需要先初始化父类
2 类的加载过程
- 类的加载机制:如果没有相应类的class,则加载class到方法区。对应着加载->验证->准备->解析-->初始化阶段
- 加载:载入class对象,不一定是从class文件获取,可以是jar包,或者动态生成的class
- 验证:校验class字节流是否符合当前jvm规范
- 准备:为 类变量 分配内存并设置变量的初始值( 默认值 )。如果是final修饰的对象则是赋值声明值
- 解析:将常量池的符号引用替换为直接引用
- 初始化:执行类构造器<client>( 注意不是对象构造器 ),为 类变量 赋值,执行静态代码块。jvm会保证子类的<client>执行之前,父类的<client>先执行完毕
- 其中验证、准备、解析3个部分称为 连接
- <clinit>方法由 静态变量赋值代码和静态代码块 组成;先执行类静态变量显示赋值代码,再到静态代码块代码
3 触发类加载的条件
- 第一次创建类的新对象时, 会触发类的加载初始化和对象的初始化函数<init>执行,这个是实例初始化,其他6个都是类初始化
- JVM启动时会先加载初始化包含main方法的类
- 调用类的静态方法(如执行invokestatic指令)
- 对类或接口的静态字段执行读写操作(即执行getstatic、putstatic指令);不过final修饰的静态字段的除外(已经赋值,String和基本类型,不包含包装类型),它被初始化为一个编译时常量表达式
- 注意 :操作静态字段时,只有直接定义这个字段的类才会被初始化;如通过其子类来操作父类中定义的静态字段,只会触发父类<clinit>的初始化而不是子类的初始化
- 调用JavaAPI中的反射方法时(比调用java.lang.Class中的方法(Class.forName),或者java.lang.reflect包中其他类的方法)
- 当初始化一个类时,其父类没有初始化,则需先触发父类的初始化(接口例外)
4 对象的实例化过程
- 对象实例化过程其实就是执行类构造函数 对应在字节码文件中的<init>()方法(称之为实例构造器);<init>()方法由 非静态变量、非静态代码块以及对应的构造器组成
- <init>()方法可以重载多个,类有几个构造器就有几个<init>()方法
- <init>()方法中的代码执行顺序为:父类变量初始化,父类代码块,父类构造器,子类变量初始化,子类代码块,子类构造器。
- 静态变量,静态代码块,普通变量,普通代码块,构造器的执行顺序
- 具有父类的子类的实例化顺序如下
5 类加载器和双亲委派规则,如何打破双亲委派规则
- 类加载器
- 通过一个类的全限定名来获取 描述此类的二进制字节流 ,实现这个动作的代码模块称为类加载器
- 任意一个类都需要其加载器和类本身来确定类在JVM的唯一性;每个类加载器都有自己的类名称空间,同一个类class由不同的加载器加载,则被JVM判断为不同的类
- 双亲委派模型
- 启动类加载器有C++代码实现,是虚拟机的一部分。负责加载lib下的类库
- 其他的类加载器有java语言实现,独立于JVM,并且继承ClassLoader
- extention ClassLoader负责加载libext目录下的类库
- application ClassLoader 负责加载用户路径下(ClassPath)的代码
- 不同的类加载器加载同一个class文件会导致出现两个类。而java给出解决方法是下层的加载器加委托上级的加载器去加载类,如果父类无法加载(在自己负责的目录找不到对应的类),而交还下层类加载器去加载。如下图
- 打破双亲委派模型
- 双亲委派模型并不是一个强制的约束模型,而是java设计者推荐给开发者的类加载实现方式
- 双亲委派模型很好的解决各个类加载基础类的同一问题(越基础的类由越上层的加载器加载),但是基础类总是作为用户代码调用的API,但是如果它的具体实现是下层的代码,此时基础类需要调用下层的代码,则需要打破双亲委派模型
- 如JNDI服务,JNDI的代码有启动类去加载(rt.jar),它需要调用由独立厂商部署在应用程序classpath下的JNDI的SPI(Service Provider Interface)代码。为了解决SPI代码加载问题,java引入了线程上下文类加载器去加载SPI代码。也就是父类加载器请求子类去完成类的加载动作
- 线程上下文类加载器,线程创建时会从父线程继承,如果全局范围没有设置过,则默认设置为application Class Loader
原作者:程序猿knight
原文链接: 详解JAVA对象实例化过程
原出处:公众号
侵删 -
【面向对象-07】继承、重写(重载)、子类对象的实例化过程、super、this关键字指向
2021-07-10 09:16:002.子类对象的实例化过程 1). 子类能否覆盖父类的构造方法 2). 隐式super语句和显式super语句 3). 使用super语句的注意事项 4). 总结super语句 3.子类this的真实指向 1). 子类对象实例化过 -
子类实例化是否会实例化父类?不会
2017-09-25 16:17:55关于对java中Class,...java中使用new来新建一个对象bottle时,可以想象成用这个模具去造了一个新瓶子,这个新瓶子是纯粹一个瓶子,什么花 纹都没有,我们当成这个就是这个bottle的属性的初始值,然后我们开始对 -
C++只在栈或堆上实例化对象
2019-09-11 20:46:44C++如何让类对象只能在堆(栈)上分配空间 一般情况下写一个类都是可以采用new在堆上...1.静态实例化对象 如 A a;的步骤为:先由编译器为对象在栈空间分配内存,移动栈顶指针,挪出适当的空间,然后在这个空间上... -
基础篇:详解JAVA对象实例化过程
2020-08-16 22:05:16类的加载过程、对象的实例过程、双亲委派模型 -
C++父类指针指向子类对象的实现原理
2021-01-02 22:11:34记得当初阿里面试的时候被问道这个问题,平时自己面对这个方法都习以为常的使用,C++多态和动态绑定不就是这么实现的嘛,但是还真没有刻意去关注其中的原理。今天特意看了相关资料,现在分享给大家。 其实这块我们... -
c++父类指针指向子类对象
2018-11-08 15:50:04c++父类指针指向子类对象 父类子类指针函数调用注意事项 1,如果以一个基础类指针指向一个衍生类对象(派生类对象),那么经由该指针只能访问基础类定义的函数(静态联翩) 2,如果以一个衍生类指针指向一个基础... -
c++ 子类构造函数初始化及父类构造初始化
2018-08-30 15:58:50我们知道,构造方法是用来初始化类对象的。如果在类中没有显式地声明构造函数,...因此,在创建子类对象时,为了初始化从父类中继承来的成员变量,编译器需要调用其父类的构造函数。如果子类的构造函数没有显示地调... -
子类集成父类时,实例化子类是否会实例化父类?
2020-07-09 15:41:52我们知道,一个抽象类是不能实例化的,那么我们只要把父类设置为抽象类,看子类实例化的时候父类是否会报错,是不是就可以知道父类有没有被实例化呢? 首先我们先写一个测试类: class Parent{ String name = ... -
C++ 子类对象当父类对象使用
2016-10-22 14:45:59子类对象当父类对象使用 1⃣️把子类对象直接赋值给父类对象(等号左边是父类对象,等号右边是子类对象) 子类对象赋值给父类对象,仅仅把继承自父类部分成员函数赋值给父类对象 赋值完成后等号左边依然是一个... -
C++学习笔记:子类构造函数中冒号的使用 — 同时创建父类和子类对象
2020-01-27 21:41:22假如父类构造函数只存在有参构造,在子类对象实例化之前,便需要创建一个父类对象,在不存在默认无参构造情况下,系统时不知道怎么为你创建父类对象的。 解决上述问题的办法,就是在子类创建时指定父类初始化方式,... -
c++实现在实例化时为每个对象添加唯一ID
2018-01-28 16:01:40这样就保证了每次实例化时的ID唯一。然后将该静态成员变量赋值给私有变量即可。具体代码如下: 类的声明: #pragma once #include class tank { public: tank(); ~tank(); void fire(); static int getCount()... -
C++,类的前置声明,c++继承,c++子类访问父类成员变量,c++头文件相互包含
2019-11-10 22:32:32假设声明两个类A和B,如果需要在A.h中定义B类对象,B b_...文章目录1,a.h 类A中实例化类B的对象2,a.cpp 可以调用类B对象的方法3,b.h 类B中不能实例化类A的对象4,b.cpp 中包含a.h,这样就可以使用类A对象中的方法... -
C++继承子类和父类修改情况
2022-03-20 20:09:09继承可看作指针指向相同的作用域,但实例化对象后,各自的某个成员变量不相干。 #include<iostream> using namespace std; class Base { public: Base(int i=2) { x = i; } int x=10; }; class C :... -
《实用C++》第41课 父类对象与子类对象之间的相互转换
2018-12-21 00:20:24本文转载自:VC驿站 ...答案:由子类对象给父类对象赋值是可以的,俗称大材小用。在赋值的时候会舍弃子类的新增成员,例如: #include "Student.h" class CXiaoStudent : public CStudent { public:... -
c++子类中初始化父类成员变量
2015-09-30 17:03:42今天在看源码遇到一个问题,刚开始没看明白,后简化为如下代码: #include ...一眼看去,在子类的构造函数中似乎是构造了一个父类的匿名变量,但运行后发现实际做的是初始化了父类的成员变量。 -
C++ 父类指针指向子类对象||子类指针指向父类对象的理解
2017-12-26 13:07:17父类子类指针函数调用注意事项 1,如果以一个基础类指针指向一个衍生类对象(派生类对象),那么经由该指针只能访问基础类定义的函数(静态联翩) 2,如果以一个衍生类指针指向一个基础类对象,必须先做强制转型动作... -
C++把子类对象当基类对象使用
2014-10-02 10:49:01★当公有继承的时候,子类对象可以当基类对象来使用。 ①把一个子类对象赋值给基类对象; 例: class Base; class Derived:public Base; Derived d; Base b; b=d; //OK,子类可以赋值给基类(把子类... -
【C++面试宝典】C++面向对象知识点总结
2022-01-07 10:04:38本文为博主准备C++面试所总结归纳的C++面向对象知识点,原文件为脑图形式,见下图。下文则是将知识点脑图转为文字形式的结果,便于读者总结归纳。 目录 面向过程和面向对象 用C 实现 C++ 的面向对象特性 双冒号... -
C++子类继承父类时如何写构造函数
2020-02-18 15:05:03构造方法用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法)。因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统... -
子类实例化时候 也会调用父类的构造函数
2019-06-10 10:30:57我们知道,构造方法是用来初始化类对象的。如果在类中没有显式地声明构造函数,...因此,在创建子类对象时,为了初始化从父类中继承来的成员变量,编译器需要调用其父类的构造函数。如果子类的构造函数没有显示地调... -
C++中,用父类实例来初始化子类实例中的父类数据
2018-12-17 17:35:02由于C++中子类没法直接得到父类对象,所以通过一个父类的实例来初始化一个子类实例的父类部分,笔者常用的有两种方法。 方法一:通过将子类实例进行类型转换,跟父类实例进行交换。代码如下:假如现在的父类为 ... -
【java基础】——java中父类声明子类实例化
2018-11-27 00:07:14问题: 1、比如两个类父类:... //创建对象这样看来 声明的时候,是父类,而在产生对象的时候,实际的对象是子类。怎么理解??? 知识点: Java的多态性 面向对象编程有三个特征,即封装、继承和多态。封装隐... -
C++子类对象隐藏了父类的同名成员函数(隐藏篇)
2017-07-18 09:39:20//可以看出子类的对象可以初始化基类的对象,并且这种方式会调用基类的拷贝构造函数 // 向士兵属性赋值"tomato" soldier.m_strName = "tomato"; // 通过士兵对象向人类属性赋值"Jim" soldier.... -
为什么要创建对象(实例化)?
2020-06-04 19:55:49一、为什么要实例化对象? 对象:属性+方法 类是指:描述一种事物的定义,是个抽象的概念 实例指:该种事物的一个具体的个体,是具体的东西 联系 类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及...
收藏数
92,836
精华内容
37,134