三、2023.9.29.C++面向对象.3

news2024/11/28 9:22:24

文章目录

  • 33、简述一下什么是面向对象?
  • 34、简述一下面向对象的三大特征?
  • 35、简述一下 C++ 的重载和重写,以及它们的区别?
  • 36、说说 C++ 的重载和重写是如何实现的?
  • 37、说说构造函数有几种,分别什么作用?
  • 38、只定义析构函数,会自动生成哪些构造函数?
  • 39、说说一个类,默认会生成哪些函数?
  • 40、说说 C++ 类对象的初始化顺序,有多重继承情况下的顺序?
  • 41、简述下向上转型和向下转型?
  • 42、简述下深拷贝和浅拷贝,如何实现深拷贝?
  • 43、 简述一下 C++ 中的多态?
  • 44、说说为什么要虚析构,为什么不能虚构造?
  • 45、说说模板类是在什么时候实现的?
  • 46、说说类继承时,派生类对不同关键字修饰的基类方法的访问权限?
  • 48、简述一下移动构造函数,什么库用到了这个函数?

33、简述一下什么是面向对象?

  1. 面向对象是一种编程思想,把一切东西看成是一个个对象,把这些对象拥有的属性变量和操作这些属性变量的函数打包成一个类来表示。
  2. 面向过程和面向对象的区别
    面向过程:根据业务逻辑从上到下写代码
    面向对象:将数据与函数绑定到一起,进行封装,加快开发程序,减少重复代码的重写过程。

34、简述一下面向对象的三大特征?

面向对象的三大特征是封装、继承、多态

  1. 封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。封装本质上是一种管理,不想给别人看到的,我们protected/private把成员封装起来。开放一些共有的成员函数对成员合理的访问。

  2. 继承:可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
    在这里插入图片描述

  3. 多态:用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。实现多态,有二种方式,重写,重载。

35、简述一下 C++ 的重载和重写,以及它们的区别?

  1. 重写
    是指派生类中存在重新定义的函数其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。只有函数体不同(花括号内),派生类对象调用时会调用派生类的重写函数,不会调用被重写函数重写的基类中被重写的函数必须有virtual修饰。
#include<bits/stdc++.h>
using namespace std;
class A {
public:
	virtual void fun() {
	cout << "A";
	}
};
class B : public A
{
public:
	virtual void fun() {
	cout << "B";
	}
};
int main(void)
{
	A* a = new B();
	a->fun();//输出B,A类中的fun在B类中重写
}
  1. 重载
    我们在平时写代码中会用到几个函数但是他们的实现功能相同,但是有些细节却不同。函数重载是指同一可访问区内被声明的几个具有不同参数列(参数的类型,个数,顺序不同)的同名函数,根据参数列表确定调用哪个函数,重载不关心函数返回类型。
#include<bits/stdc++.h>
using namespace std;
class A
{
	void fun() {};
	void fun(int i) {};
	void fun(int i, int j) {};
	void fun1(int i,int j){};
};

36、说说 C++ 的重载和重写是如何实现的?

  1. 重载:C++利用命名倾轧(name mangling)技术,来改名函数名,区分参数不同的同名函数。命名倾轧是在编译阶段完成的。编译时将参数类型加入以区分不同。
  2. 重写:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。
    虚函数需要注意的地方:
  • 用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。
  • 存在虚函数的类都有一个一维的虚函数表叫做虚表,类的对象有一个指向虚表开始的虚指针。 虚表是和类对应的,虚表指针是和对象对应的。
  • 多态性是一个接口多种实现,是面向对象的核心,分为类的多态性和函数的多态性。
  • 重写用虚函数来实现,结合动态绑定。
  • 纯虚函数是虚函数再加上 = 0。
  • 抽象类是指包括至少一个纯虚函数的类。
  • 纯虚函数:virtual void fun()=0。即抽象类必须在子类实现这个函数,即先有名称,没有内容,在派生类实现内容。

37、说说构造函数有几种,分别什么作用?

C++中的构造函数可以分为4类:默认构造函数、初始化构造函数、拷贝构造函数、移动构造函数。

  1. 默认构造函数和初始化构造函数。 在定义类的对象的时候,完成对象的初始化工作。
    注意:有了有参的构造了,编译器就不提供默认的构造函数。
class Student
{
public:
//默认构造函数
	Student() {
		num=1001;
		age=18;
	}
//初始化构造函数
Student(int n,int a):num(n),age(a){}
private:
	int num;
	int age;
};
int main() {
//用默认构造函数初始化对象S1
	Student s1;
//用初始化构造函数初始化对象S2
	Student s2(1002,18);
	return 0;
}
  1. 拷贝构造函数
#include "iostream.h"
class Test {
	int i;
	int *p;
public:
	Test(int ai,int value) {
	i = ai;
	p = new int(value);
}
	~Test() {
	delete p;
	}
Test(const Test& t) {
	this->i = t.i;
	this->p = new int(*t.p);
	}
};
//复制构造函数用于复制本类的对象
int main(int argc, char* argv[])
{
	Test t1(1,2);
	Test t2(t1);//将对象t1复制给t2。注意复制和赋值的概念不同
	return 0;
}

赋值构造函数默认实现的是值拷贝(浅拷贝)。
3. 移动构造函数。用于将其他类型的变量,隐式转换为本类对象。下面的转换构造函数,将int类型的r转换为Student类型的对象,对象的age为r,num为1004。

Student(int r)int num=1004int age= r;
}

38、只定义析构函数,会自动生成哪些构造函数?

只定义了析构函数,编译器将自动为我们生成拷贝构造函数和默认构造函数。
默认构造函数和初始化构造函数。 在定义类的对象的时候,完成对象的初始化工作。

class Student
{
public:
//默认构造函数
	Student() {
		num=1001;
		age=18;}
//初始化构造函数
Student(int n,int a):num(n),age(a){}
private:
	int num;
	int age;
};
int main()
{
//用默认构造函数初始化对象S1
	Student s1;
//用初始化构造函数初始化对象S2
	Student s2(1002,18);
return 0;
}

有了有参的构造了,编译器就不提供默认的构造函数。
拷贝构造函数。

#include "iostream.h"
class Test {
	int i;
	int *p;
public:
	Test(int ai,int value) {
	i = ai;
	p = new int(value);
}
	~Test() {
	delete p;
	}
Test(const Test& t) {
	this->i = t.i;
	this->p = new int(*t.p);
	}
};
//复制构造函数用于复制本类的对象
int main(int argc, char* argv[])
{
	Test t1(1,2);
	Test t2(t1);//将对象t1复制给t2。注意复制和赋值的概念不同
	return 0;
}
class HasPtr
{
public:
	HasPtr(const string& s = string()) :ps(new string(s)), i(0) {}
	~HasPtr() { delete ps; }
private:
	string * ps;
	int i;
};
HasPtr f(HasPtr hp)
{
	HasPtr ret = hp;
	///... 其他操作
	return ret;
}
如果类外面有这样一个

当函数执行完了之后,将会调用hp和ret的析构函数,将hp和ret的成员ps给delete掉,但是由于ret和hp指向了同一个对象,因此该对象的ps成员被delete了两次,这样产生一个未定义的错误,所以说,如果一个类定义了析构函数,那么它要定义自己的拷贝构造函数和默认构造函数。

39、说说一个类,默认会生成哪些函数?

定义一个空类:

  • 无参的构造函数
class Empty {
};
  • 拷贝构造函数
    拷贝构造函数用于复制本类的对象
Empty(const Empty& copy) {
}
  • 赋值运算符
Empty& operator = (const Empty& copy) {
}
  • 析构函数(非虚)
~Empty() {
}

40、说说 C++ 类对象的初始化顺序,有多重继承情况下的顺序?

  1. 创建派生类的对象,基类的构造函数优先被调用(也优先于派生类里的成员类);
  2. 如果类里面有成员类,成员类的构造函数优先被调用;(也优先于该类本身的构造函数)
  3. 基类构造函数如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现的顺序而不是它们在成员初始化表中的顺序;
  4. 成员类对象构造函数如果有多个成员类对象,则构造函数的调用顺序是对象在类中被声明的顺序而不是它们出现在成员初始化表中的顺序;
  5. 派生类构造函数,作为一般规则派生类构造函数应该不能直接向一个基类数据成员赋值而是把值传递给适当的基类构造函数。
  6. 综上可以得出,初始化顺序:
    父类构造函数–>成员类对象构造函数–>自身构造函数
    其中成员变量的初始化与声明顺序有关,构造函数的调用顺序是类派生列表中的顺序。
    析构顺序和构造顺序相反。

41、简述下向上转型和向下转型?

  1. 子类转换为父类:向上转型,使用dynamic_cast(expression),这种转换相对来说比较安全不会有数据的丢失
  2. 父类转换为子类:向下转型,可以使用强制转换,这种转换时不安全的,会导致数据的丢失,原因是父类的指针或者引用的内存中可能不包含子类的成员的内存

42、简述下深拷贝和浅拷贝,如何实现深拷贝?

  1. 浅拷贝:又称值拷贝,将源对象的值拷贝到目标对象中去,本质上来说源对象和目标对象共用一份实体,只是所引用的变量名不同,地址其实还是相同的。举个简单的例子,你的小名叫西西,大名叫冬冬,当别人叫你西西或者冬冬的时候你都会答应,这两个名字虽然不相同,但是都指的是你。
  2. 深拷贝,拷贝的时候先开辟出和源对象大小一样的空间,然后将源对象里的内容拷贝到目标对象中去,这样两个指针就指向了不同的内存位置。并且里面的内容是一样的,深拷贝情况下,不会出现重复释放同一块内存的错误。

43、 简述一下 C++ 中的多态?

由于派生类重写基类方法,然后用基类引用指向派生类对象,调用方法时候会进行动态绑定,这就是多态。

  • 不同的对象收到同一消息可以进行不同的响应,产生完全不同的结果。
    多态分为静态多态和动态多态:
  1. 静态多态:编译器在编译期间完成的,编译器会根据实参类型来推断该调用哪个函数,如果有对应的函数,就调用,没有则在编译时报错。
include<iostream>

using namespace std;

int Add(int a,int b)//1 {
	return a+b;
}
	char Add(char a,char b)//2 {
	return a+b;
}
int main() {
	cout<<Add(666,888)<<endl;//1
	cout<<Add('1','2');//2
	return 0;
}
  1. 动态多态:其实要实现动态多态,需要几个条件——即动态绑定条件:
  • 虚函数。基类中必须有虚函数,在派生类中必须重写虚函数。
  • 通过基类类型的指针或引用来调用虚函数。

44、说说为什么要虚析构,为什么不能虚构造?

  1. 虚析构:将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。如果基类的析构函数不是虚函数,在特定情况下会导致派生类无法被析构。
  • 用派生类类型指针绑定派生类实例,析构的时候,不管基类析构函数是不是虚函数,都会正常析构
  • 用基类类型指针绑定派生类实例,析构的时候,如果基类析构函数不是虚函数,则只会析构基类,不会析构派生类对象,从而造成内存泄漏。为什么会出现这种现象呢,个人认为析构的时候如果没有虚函数的动态绑定功能,就只根据指针的类型来进行的,而不是根据指针绑定的对象来进行,所以只是调用了基类的析构函数;如果基类的析构函数是虚函数,则析构的时候就要根据指针绑定的对象来调用对应的析构函数了。
    C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。
  1. 不能虚构造:
  • 从存储空间角度:虚函数对应一个vtale,这个表的地址是存储在对象的内存空间的。如果将构
    造函数设置为虚函数,就需要到vtable 中调用,可是对象还没有实例化,没有内存空间分配,如何调用。(悖论)
  • 从实现上看,vbtl 在构造函数调用后才建立,因而构造函数不可能成为虚函数。

45、说说模板类是在什么时候实现的?

  1. 模板实例化:模板的实例化分为显示实例化和隐式实例化,前者是研发人员明确的告诉模板应该使用什么样的类型去生成具体的类或函数,后者是在编译的过程中由编译器来决定使用什么类型来实例化一个模板不管是显示实例化或隐式实例化,最终生成的类或函数完全是按照模板的定义来实现的。
  2. 模板具体化:当模板使用某种类型类型实例化后生成的类或函数不能满足需要时,可以考虑对模板进行具体化。具体化时可以修改原模板的定义,当使用该类型时,按照具体化后的定义实现,具体化相当于对某种类型进行特殊处理。
#include <iostream>
using namespace std;
// #1 模板定义
template<class T>
struct TemplateStruct {
	TemplateStruct() {
		cout << sizeof(T) << endl;
	}
};
// #2 模板显示实例化
template struct TemplateStruct<int>;
// #3 模板具体化
template<> struct TemplateStruct<double> {
	TemplateStruct() {
	cout << "--8--" << endl;
	}
};
int main() {
	TemplateStruct<int> intStruct;
	TemplateStruct<double> doubleStruct;
	// #4 模板隐式实例化
	TemplateStruct<char> llStruct;
}

46、说说类继承时,派生类对不同关键字修饰的基类方法的访问权限?

类中的成员可以分为三种类型,分别为public成员、protected成员、public成员。类中可以直接访问自己类的public、protected、private成员,但类对象只能访问自己类的public成员。

  1. public继承:派生类可以访问基类的public、protected成员,不可以访问基类的private成员;派生类对象可以访问基类的public成员,不可以访问基类的protected、private成员。
  2. protected继承:派生类可以访问基类的public、protected成员,不可以访问基类的private成员;派生类对象不可以访问基类的public、protected、private成员。
  3. private继承:派生类可以访问基类的public、protected成员,不可以访问基类的private成员;派生类对象不可以访问基类的public、protected、private成员。

48、简述一下移动构造函数,什么库用到了这个函数?

移动也使用一个对象的值设置另一个对象的值。移动实现的是对象值真实的转移(源对象到目的对象):源对象将丢失其内容,其内容将被目的对象占有。移动操作的发生的时候,是当移动值的对象是未命名的对象的时候。这里未命名的对象就是那些临时变量,甚至都不会有名称。典型的未命名对象就是函数的返回值或者类型转换的对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1052540.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(二) gitblit用户使用教程

(一)gitblit安装教程 (二) gitblit用户使用教程 (三) gitblit管理员手册 目录 网页访问git客户端设置推送错误配置查看当前配置 日常使用仓库分组my profile修改上传代码简洁 网页访问 点击Advanced... 点击Accept the Risk and Contiue 初始用户名和密码都是admin,点击login…

使用SDKMAN在Linux系统上安装JDK

本文使用的Linux发行版为Rocky Linux 9.2&#xff0c;可以当做CentOS的平替产品。 SDKMAN是一个sdk包管理工具&#xff0c;通过自带的命令可以快速切换软件环境&#xff0c; 官网地址&#xff1a;https://sdkman.io/。 1、安装sdkman&#xff1a; # curl -s "https://ge…

1 论文笔记:Efficient Trajectory Similarity Computation with ContrastiveLearning

2022CIKM 1 intro 1.1 背景 轨迹相似度计算是轨迹分析任务&#xff08;相似子轨迹搜索、轨迹预测和轨迹聚类&#xff09;最基础的组件之一现有的关于轨迹相似度计算的研究主要可以分为两大类&#xff1a; 传统方法 DTW、EDR、EDwP等二次计算复杂度O(n^2)缺乏稳健性 会受到非…

【机器学习】训练集/验证集/测试集释疑

文章目录 序言1. 训练集、验证集、测试集是什么2. 为什么需要验证集3. 验证集是必须的吗4. 验证集和测试集上的表现会不同吗5. 如何从Train/Test Set划分Validation Set6. 训练集、验证集和测试集的比例怎么设置7. 模型表现不好时测试集可以反复使用来调整模型吗8. 训练集、验证…

设计模式6、适配器模式 Adapter

解释说明&#xff1a;将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作 目标接口&#xff08;Target&#xff09;&#xff1a;当前系统所期待的接口&#xff0c;它可以是抽象类或接口 适配者&#xff08;Adaptee&#xff09;&#xff1a…

堆的介绍、堆的向上、 向下调整法与基本功能实现

&#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;数据结构 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学习编程知识 堆 二叉树的顺序结构堆的概念&#xff1a;堆的…

汽车电子——产品标准规范汇总和梳理(开发体系)

文章目录 前言 一、设计架构 二、安全可靠 三、测试验证 四、过程能力 五、质量管理 六、开发指南 总结 前言 见《汽车电子——产品标准规范汇总和梳理》 一、设计架构 《Autosar R22-11 汽车开放系统体系架构》 二、安全可靠 《GB/T 34590.1-2022&#xff08;ISO 262…

零代码编程:用ChatGPT批量自动下载archive.org上的音频书

http://archive.org 是一个神奇的网站&#xff0c;可以下载各种古旧的软件、书籍、音频、视频&#xff0c;还可以搜索各个网站的历史网页。 比如说&#xff0c;一些儿童故事音频就可以在http://archive.org下载到&#xff0c;可以用来做英语听力启蒙用。 举个例子&#xff0c…

【开发篇】四、数据源、JdbcTemplate、内嵌H2

文章目录 1、数据源DataSource2、SpringBoot的内嵌数据源对象3、Spring的内置持久化方案JdbcTemplate4、SpringBoot内嵌数据库5、内嵌数据库H2的访问 1、数据源DataSource 了解数据源这个概念前&#xff0c;先看下原生JDBC的基本步骤&#xff1a; Connection conn null; State…

【JVM】双亲委派模型

双亲委派模型 1. 什么是双亲委派模型2. 双亲委派模型的优点 1. 什么是双亲委派模型 提到 类加载 机制&#xff0c;不得不提的一个概念就是“双亲委派模型”。 双亲委派模型指的就是 JVM 中的类加载器如何根据类的全限定名找到 .class 文件的过程 类加载器: JVM 里面专门提供…

坠落防护 挂点装置

声明 本文是学习GB 30862-2014 坠落防护 挂点装置. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了高处坠落防护挂点装置的技术要求、检验方法、检验规则及标识。 本标准适用于防护高处坠落的挂点装置。 本标准不适用于体育及消…

【C++】unordered_set与unordered_map的封装

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

Java | Maven(知识点查询)

文章目录 Maven知识速查1. Maven概述2. Maven的作用3. Maven的下载4. Maven的环境配置5. Maven 的基础组成5.1 Maven仓库5.1.1 本地仓库配置&#xff1a;5.1.2 中央仓库配置&#xff1a;5.1.3 镜像仓库配置 5.2 Maven坐标 6. Maven项目6.1 手工创建Maven项目6.2 自动构建项目 7…

7、Docker网络

docker网络模式能干嘛&#xff1f; 容器间的互联和通信以及端口映射 容器IP变动时候可以通过服务名直接网络通信而不受到影响 docker 网络模式采用的是桥接模式&#xff0c;当我们创建了一个容器后docker网络就会帮我们创建一个虚拟网卡&#xff0c;这个虚拟网卡和我们的容器网…

火热报名中 | 2天峰会、20+热门议题,AutoESG 2023数智低碳---中国汽车碳管理创新峰会亮点抢先看!

在碳中和的背景下&#xff0c;减碳之风吹遍全球&#xff0c;而汽车行业则由于产业链长、辐射面广、碳排放总量增长快、单车碳强度高的特点&#xff0c;成为各国碳排放管理的监管重点&#xff0c;聚焦汽车业的碳博弈也逐步升级。 2020年&#xff0c;国务院办公厅印发的《新能源…

Linux高级应用——web网站服务(2)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 目录 前言 一. httpd服务访问控制概述 1.为什么要…

用友U8 CRM客户关系管理任意文件上传漏洞复现【附POC】

文章目录 用友U8 CRM客户关系管理任意文件上传漏洞复现0x01 前言0x02 漏洞描述0x03 影响平台0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现4.访问shell地址 0x06 整改建议 用友U8 CRM客户关系管理任意文件上传漏洞复现 0x01 前言 免责声明&#xff1a;请勿利用文…

牛客 ( 计算几何

#include <bits/stdc.h> using namespace std; using ll long long; using PII pair<double , double>; int n; PII p[3000010]; vector<PII> pp; PII yuan(PII a , PII b , PII c) {//已知三个点确定圆的半径和圆心double x1 a.first,x2 b.first,x3 c.…

Spring面试题25:Spring如何控制bean加载先后顺序

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Spring如何控制bean加载先后顺序 Spring框架提供了两种方式来控制Bean的加载顺序: depends-on属性:通过在Bean配置中使用depends-on属性,可以明…