专栏首页循迹漫聊虚幻引擎C++中面向对象部分知识整理

C++中面向对象部分知识整理

近期准备求职面试。 将C++中面向对象部分的基础知识复习整理一下。

在C++中,用来定义自己的抽象数据类型(abstract data type)

类的定义和声明

简单的来说,类就是定义了一个新的类型和新的作用域。

类定义:概要

类成员

每个类可以没有成员也可以定义多个成员,成员可以是数据函数类型别名。 一个类可以包含若干公有的(public)**、私有的(private)受保护的(protected)部分**。

访问标号
  • public:**使用public访问标号**定义的成员可被该类型的所有代码访问,类的用户、该类的派生类也都可以访问。
  • private:**使用private访问标号定义的成员可被类中其他的成员**访问,不能被类的用户、该类的派生类访问。
  • protected:**使用protected访问标号定义的成员,可以认为它是public和private的混合,像private一样,使用类的用户不能直接访问,像public一样,protected成员可以被以该类为基类的派生类**访问。
构造函数

创建一个类类型时,编译器会自动使用一个构造函数来初始化对象。

构造函数:定义如何初始化的类成员函数。(C++ Primer 4th,2.3.3-2,P43)

另:C++支持两种初始化方式:(C++ Primer 4th,2.3.3-1,P42)

  1. 复制初始化(copy-initialization):使用语法为直接使用等号(=).
  2. 直接初始化(direct-initialization):使用语法为把初始化式放在括号中().
int ival=1024;//复制初始化(copy-initialization)
int ival(1024);//直接初始化(direct-initialization)
成员函数

在类内部,声明成员函数是必须的,而定义成员函数则是可选的。

在类内部定义的函数默认为inline(内联函数).(C++ Primer 4th,12.1.1-3,P369) 内联函数:在调用节点处内联展开,避免函数调用开销。因为调用函数比直接执行表达式要慢得多。(C++ Primer 4th,7.6,P221) 调用函数要做很多工作:

  1. 调用前先保存寄存器,并在返回时恢复;
  2. 复制实参;
  3. 程序还必须转向一个新位置执行。

在类外部定义的成员函数必须指明他们是在类的作用域中的。 可以使用**::作用域操作符**来指定:

class testClass{
public:
	//成员函数printHelloWorld在类中声明但不定义。
	void printHelloWorld();
};
//testClass类的成员函数printHelloWorld在类外部定义必须使用作用域操作符指定
void testClass::printHelloWorld(){
	cout<<"HelloWorld"<<endl;
}

成员函数有一个附加的隐含实参,将函数绑定到函数的对象——this指针 当我们定义:

testClass obj;
obj.printHelloWorld();

调用obj对象的printHelloWorld函数,如果在printHelloWorld函数内对testClass类成员的引用就是对obj对象的成员的引用。

const成员函数

将关键字const加在形参表之后,就可以将成员函数声明为常量const成员不能改变其所操作的对象的数据成员。 const关键字必须同时出现在声明和定义中,若只出现一次则会出现一个编译错误。

//我们可以在testClass类中的public访问标号下添加如下成员函数声明
int don_tChangeMemberData() const;

//该函数的定义必须也要写const关键字
int testClass::don_tChangeMemberData() const{
	//...	
}

const的作用如同函数名描述的那样:)

数据抽象和封装

类背后蕴含的思想是数据抽象封装

数据抽象是一种依赖于接口和实现分离的编程(设计)技术。 通过数据抽象,使用一个类型的程序猿仅需要了解类型的接口,他们可以抽象地考虑该类型做什么,而不是具体地考虑类型如何工作。 封装是一种将低层次的元素组合起来形成新的、高层次实体的技术。 函数是封装的一种形式:函数所执行的细节行为被封装在函数本身这个更大的实体中。被封装的元素隐藏了它们的实现细节——可以调用一个函数,但不能访问它所执行的语句。

标准库类型vector同时具备数据抽象和封装的特性。数组在概念上类似于vector,但既不是抽象的也不是封装的。可以通过访问存放数组的内存来直接操纵数组。

访问标号实施抽象和封装

在C++中,使用访问标号来定义类的抽象接口和实施封装。

注意:一个类可以没有访问标号也可以拥有多个访问标号。访问标号这里我们已经简单的介绍了三种访问标号之间的区别了。

一个访问标号出现的次数通常是没有限制的。每个访问标号指定了随后的成员定义的访问级别。这个指定范围持续有效,直至遇到下一个访问标号或看到类定义体的右花括号为止

可以在任意的访问标号出现之前定义类成员。 在类的花括号之后、第一个访问标号之前定义的成员的访问级别依赖于类是如何定义的。

数据抽象和封装的好处

数据抽象和封装提供了两个重要的有点:

  • 避免类内部出现无意的,可能破坏对象状态的用户级错误。
  • 随时间推移可以根据需求改变或缺陷(bug)报告来完善类实现,而无需改变用户级代码。

改变头文件中的类定义可有效地改变包含该头文件的妹子资源文件的额程序文本,所以,当类发生改变时,使用该类的代码必须重新编译。

关于类定义的更多内容

同一类型的多个数据成员

类的数据成员的声明类似于普通变量的声明。 如果一个类具有多个同一类型的数据成员,则这些成员可以在一个成员声明中指定,声明的顺序从左至右。(构造函数中需要用到成员的定义顺序)

用typedef来简化类

如代码

class testClass{
public:
	typedef string::size_type index;
private:
	// index type is string::size_type
	index height,width;
};
成员函数可被重载

成员函数可以被重载。但重载操作符有特殊规则,是个例外。

成员函数只能重载奔雷的其他成员函数。 类的成员函数与普通的成员函数以及在其他类中声明的函数不相关,也不能重载它们。

重载的成员函数和普通函数应用相同的规则:两个重载成员的形参数量和类型不能完全相同。调用非成员重载函数所用到的函数匹配过程也应用于重载成员函数的调用。

class testClass{
public:
	void get() const{cout<<"Use empty parameter get version"<<endl;}
	void get(int x) const{cout<<"Use a int type parameter get version"<<endl;}
};

假设我们定义了一个该类对象classTemp,则我们对get函数调用的方式会决定使用get的哪一个版本:

testClass classTemp;
//调用无参数版本的get
classTemp.get();
//调用接收一个int型参数的get版本
classTemp.get(11);
显式指定inline成员函数

在类内部定义成员函数,将自动作为inline处理。 也就是说当他们被调用时,编译器将试图在同一行内扩展该函数,也可以显式地将成员函数声明为inline.

class testClass{
public:
	inline void get() const{
		cout<<"Use empty parameter get version"<<endl;
	}
	inline void get(int x) const;
};
inline void testClass::get(int x) const{
		cout<<"Use a int type parameter get version"<<endl;
}

可以在类定义体内部之定义一个成员为inline,作为其声明的一部分。也可以在类定义体外部定义上指定inline.在声明和定义出指定inline都是合法的。在类外部定义inline的一个好处是使类比较容易阅读。

类声明与类定义

一旦遇到右花括号,类的定义就结束了。并且,一旦定义了类,那么我们就知道了所有的类成员,以及存储该类所需的存储空间。

在一个给定的源文件中,一个类只能被定义一次。

将类定义放在头文件中,可以保证在每个实用类的文件中以同样的方式定义类。 使用**头文件保护符(header guard)**来避免多重包含(保证类定义只包含一次)

#ifndef TESTCLASS_H
#define TESTCLASS_H
	//类定义
#endif

也可以声明一个类而不定义它

class testClass;

这个声明成为前向声明,在声名之后,定义之前,类testClass是一个**不完全类型(incompete type)**,即已知testClass是一个类型,但不知道包含那些成员。

不完全类型只能以有限的方式使用

  • 不能定义该类型的对象
  • 用于定义指向该类类型的引用或指针
  • 用于声明该类型作为形参类型或返回类型的函数

在创建类的对象之前,必须完整的定义该类。 必须定义类,而不只是声明类,这样编译器就会给类的对象预定相应的存储空间。 同样,在使用引用或指针访问类的成员之前,必须已经定义类

类的前向声明一般用来编写相互依赖的类。

为类的成员使用类声明

前面写道,只有当类定义已经在前面出现过数据成员才能被指定为该类类型。如果该类类型是不完全类型,那么数据成员只能是指向该类类型的指针或引用。

因为只有当类定义体完成之后才能定义类,因此类不能具有自身类型的数据成员。然而,只要类名一出现就可以认为该类已经声明。因此,类的数据成员可以是指向自身类型的指针或引用。

class testClass{
	testClass *prev;
	testClass *next;
}
类对象

定义一个类,也就是定义了一个类型。一旦定义了类,就可以定义该类型的对象。定义对象时,将为其分配内存空间,但是(一般而言),定义类型时不进行存储分配(在类右括号之后分号之前)。

class testClass{
public:
	//....
private:
	int ival;
	double dval;
};

有两种方式可以定义类类型对象:

  1. 将类的名字直接用作类型名。(C++引入)
  2. 指定关键字class或struct,后面跟着类的名字。(由c语言继承而来)
testClass item1;
class testClass item2;

为什么类要以分号结束? 类的定义以分号结束。分号是必须的,因为在类定义之后可以接一个对象定义列表。定义必须以分号结束。 但是将对象定义成类定义的一部分是个坏主意,会使发生的操作难以理解。

隐含的this指针

类的成员函数有一个附加的隐含形参,即指向该类对象的一个指针。这个隐含指针命名为this,与调用成员函数的对象绑定在一起。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python小知识点(5)--面向对象部分

    世间万物,皆可分类。--------------------手机《--------------某一个分类

    wfaceboss
  • 什么是面向对象? | Java核心知识点整理

    相信很多Java开发者,在最初接触Java的时候就听说过,Java是一种面向对象的开发语言,那么什么是面向对象呢?

    海拥
  • C# 基础知识系列- 4 面向对象

    面向对象是一个抽象的概念,其本质就是对事物以抽象的方式建立对应的模型。简单来讲,比如我有一只钢笔,那么我就可以通过分析,可以得到 这只钢笔的材第是塑料,品牌是个...

    程序员小高
  • php面向对象重点知识分享

    通常将属性设为protected,利用getXxx和setXxx方法来设置和获取属性的值,避免外部随意的更改,同时还可以对对象进行过滤。

    砸漏
  • JavaScript面向对象编程指南 第一、二章知识点整理

    小胖
  • Python中关于面向对象的相关知识

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    村雨遥
  • 面向对象(二十三)-网络 Socket 理论知识

    计算机在网络上都有一个 IP地址,每个计算机都有端口,端口范围在0-65535之间。 端口,是计算机上 应用程序通讯所用的地址。

    孙寅
  • 面向对象(二十一)-多线程 理论知识

    进程: 系统中正在运行的程序。 一条进程就代表当前系统中正在运行的一个程序。 每个进程都是相互独立的,每个进程中都有属于自己的内存空间。 线程:一个进程想要...

    孙寅
  • 史上最全的Python面向对象知识点疏理

    ? 面向对象技术简介 类: 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。class 类变量:类变量...

    小小科
  • 史上最全的Python面向对象知识点疏理

    源 / Python编程 文 / 朱小朱 面向对象技术简介 类: 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类...

    顶级程序员
  • Java面向对象基础知识(3)一个典型类的定义和面向对象的内存分析

    为了让大家对于面向对象编程有更深入的了解,我们要对程序的执行过程中,内存到底发生了什么变化进行剖析,让大家做到“心中有数”,通过更加形象方式理解程序的执行方式。

    nuts
  • 《挑战30天C++入门极限》理解C++面向对象程序设计中的抽象理论

      为了更容易学习便于理解,我们的图例是以有两个小孩围成一圈,并且设置报数的数为1的情况来制作的。   上面的两种解决Josephus问题的解决办法从代码...

    landv
  • 如何讲清楚 Java 面向对象的问题与知识?(类与对象,封装,继承,多态,接口,内部类...)

    这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解。所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初...

    BWH_Steven
  • python-面向对象速查表-内置方法-内置函数-内置属性(只整理了部分内容)

    suwanbin
  • 学习路线

    我们可以通过今年最新的TIOBE编程语言排行榜看到,JAVA在“昨天”、和“今天”都强势霸据榜单第一名,哇哦,看起来好像很厉害,那么为我们又为什么要学习Java...

    BWH_Steven
  • C/C++学习路线

    随着互联网及互联网+深入蓬勃的发展,经过40余年的时间洗礼,C/C++俨然已成为一门贵族语言,出色的性能使之成为高级语言中的性能王者。而在今天,它又扮演着什么样...

    Sindsun
  • 终于,我也要出一本C#的书了 - 我的写作历程与C#书单推荐

    我于2012年3月开始工作,到现在马上就满六年了。这六年里,我从一个连Sql server是什么都不知道,只会写最简单的c#的程序员开始做起,一步一步从一个籍籍...

    s055523
  • C 语言与 C++ 学习路线、书籍、视频推荐和资料,值得收藏!

    C 语言是最接近计算机的语言,很多时间,我们都会发现,C 语言是非常有必要学习的。

    C语言与CPP编程
  • c++学习路线

    C++常用在后端服务器,移动互联网后端,经典Windows界面开发,移动互联网端界面开发,跨平台界面开发,图形分析,系统架构,应用设计,还有现在最为流...

    C语言与CPP编程

扫码关注云+社区

领取腾讯云代金券