前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++基础——C++面向对象之类、对象与继承基础总结(类和对象概念、构造函数与析构函数、this指针、继承)

C++基础——C++面向对象之类、对象与继承基础总结(类和对象概念、构造函数与析构函数、this指针、继承)

作者头像
Winter_world
发布2023-03-08 10:57:28
7720
发布2023-03-08 10:57:28
举报

【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来!

QT开发实战 嵌入式通用开发实战 《从0到1学习嵌入式Linux开发》 《Android开发实战》 《实用硬件方案设计》

长期持续带来更多案例与技术文章分享;

欢迎商业项目咨询,10年+软硬全栈内功,助力解决您的尊贵需求。

原文链接:https://cloud.tencent.com/developer/article/2235700

——————————————————————————————————

目录

0 引言

1 类和对象

1.1 类和对象基本概念 

1.2 构造函数和析构函数

1.3 this指针

2 继承

3 总结


0 引言

        C++面向对象有三大特征,分别是继承、多态和封装,接下来的三篇博文将会对这三大特性分别进行总结,并结合实例编程测试,加深理解,本次博文首先总结下C++的继承特征。

1 类和对象

1.1 类和对象基本概念 

       C++ 在 C 语言的基础上增加了面向对象编程, C++ 支持面向对象程序设计。类是 C++的核心特性,通常被称为用户定义的类型。类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员,函数在一个类中被称为类的成员(C++中的类跟Java语言实在太像了)。

        举个例子,一个人,他有名字、年龄等等这些属性,同时人也会吃饭、走路、睡觉,将人统称为一个类,类就抽象出来的一个概念,具体到是哪个人,就叫做对象。从类中实例化对象有两种方法:从栈中实例化、从堆中实例化。

下面自定义一个people类,看下如何自定义类和使用对象的。

在Ubuntu下新建一个03_class_people目录,其下新建一个03_class_people.cpp文件,代码如下:

代码语言:javascript
复制
#include <iostream>
#include <string>
using namespace std;

class People
{
public:
	string name;
	int age;
	void speak(){
		cout << "my name is " << name << ", age is " << age << endl;
	}	
};

int main()
{
	//从栈中实例化对象
	People people1;
	people1.name = "小芳";
	people1.age = 18;
	people1.speak();

	//从堆中实例化对象
	People *people2 = new People();
	if(NULL == people2){
		return 0;	
	}
	people2->name = "张三";
	people2->age = 20;
	people2->speak();

	delete people2;
	people2 = NULL;
	return 0;
}

首先,定义了一个People类,内部定义了两个变量,一个方法,其中string 是C++的数据类型,使用频率很高;使用了public(公有的)访问限定符,目的为了下面使用类时调用这些变量和方法,若不加限定,默认的private(私有的);

然后,从栈中实例化一个对象people1,并为people1中的成员变量赋值,然后调用对象中的speak()方法打印输出;

接着,从堆中实例化一个对象people2(使用关键字 new 的都是从堆中实例化对象),这种方式需要开辟内存,指针会指向对应的内存空间,若申请内存失败,指针就会指向NULL,程序退出;赋值后,同样打印输出,最后释放内存。

编译程序,运行测试下:

        从上面我们可以理清了C++中类和对象的概念,从类实例化出来的就是对象,对象拥有类的属性,可以从栈或堆中实例化出来。

1.2 构造函数和析构函数

        构造函数在对象实例化时被系统自动调用,仅且调用一次。实际上定义类时, 如果没有人为定义构造函数和析构函数, 编译器就会生成一个构造函数和析构函数, 只是他们不会做任何事情,所以对我们来说不会关注到。构造函数特点:

  • 1)构造函数必须与类名同名;
  • 2)可以重载;
  • 3)没有返回类型,即使是 void 也不行。

        析构函数与构造函数相反, 在对象结束其生命周期时系统自动执行析构函数。析构函数的特点:

  • 1)析构函数的格式为~类名();
  • 2)调用时释放内存(资源);
  • 3)~类名()不能加参数;
  • 4)没有返回值,即使是 void 也不行。

下面举例说明这两个函数的使用。

在Ubuntu下新建一个04_structor目录,在其中新建一个04_structor.cpp文件,代码如下:

代码语言:javascript
复制
#include <iostream>
#include <string>
using namespace std;

class People
{
public:
	People()
	{
		cout<<"构造函数执行!"<<endl;
	};
	~People()
	{
		cout<<"析构函数执行!"<<endl;
	}
};

int main()
{
	People people;
	cout<<"构造与析构函数示例"<<endl;
    	return 0;
}

        仍然是定义一个People类,然后自己写一个构造函数和析构函数,在函数中及main函数中打印信息。

我们运行程序,查看下打印的顺序:

        可见执行顺序是:构造函数-》主函数-》析构函数,实例化对象时调用构造函数,然后main函数打印输出,最后对象生命周期结束时执行析构函数。

1.3 this指针

        每个对象都拥有一个 this 指针, this 指针记录对象的内存地址,在 C++中, this 指针是指向类自身数据的指针, 简单的来说就是指向当前类的当前实例对象。类的 this 指针有以下特点:

  • 1)this 只能在成员函数中使用, 全局函数、静态函数都不能使用 this。 实际上,成员函数默认第一个参数为 T * const this。 如一个类里面的成员函数 int func(int p), func 的原型在编译器看来应该是 int func(T * const this,int p);
  • 2)this 在成员函数的开始前构造,在成员函数的结束后清除;
  • 3)this 指针会因编译器不同而有不同的放置位置。可能是栈,也可能是寄存器,甚至全局变量。

下面举例说明this的用法。

在Ubuntu下新建一个05_this_pointer目录,在其中新建一个05_this_pointer.cpp文件,代码如下:

代码语言:javascript
复制
#include <iostream>
#include <string>
using namespace std;

class People
{
public:
	string name;
	void func(); 
};

int main()
{
	People people;
	people.func();
    	return 0;
}

void People::func()
{
	this->name = "小芳";
	cout << "她的名字叫:" << this->name << endl;
}

在类的成员函数中使用了this指针,指向类中的name成员,赋值后并将其打印了出来。

编译运行程序:

2 继承

        有了上面的类和对象基础,才好理解下面要讲的继承。继承允许我们依据一个类来定义另一个类,这使得创建和维护一个应用程序变得更容易,也可达到重用代码功能和提高执行效率的效果。

 当创建一个类时,不用重新编写新的数据成员和成员函数,只需指定新建的类(派生类)继承了一个已有的类(基类)的成员即可,在 Qt 里大量的使用这种特性, 当 Qt 里的类不满足自己的要求时,我们可以重写这个类,就是通过继承需要重写的类,来实现自己的类的功能。

 一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。

        类派生列表以一个或多个基类命名,形式如下:

代码语言:javascript
复制
class derived-class: access-specifier base-class

access-specifier:访问修饰符,与类的访问修饰限定符一样,可以使用public、 protected 或 private,若未使用,默认为private;

base-class:已经定义的某个类的名称;

下面对比下3种访问修饰符:

  • 1)公有继承(public):当一个类派生继承公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
  • 2)保护继承(protected): 当一个类派生继承保护基类时,基类的公有和保护成员将成为派生类的保护成员。
  • 3)私有继承(private):当一个类派生继承私有基类时,基类的公有和保护成员将成为派生类的私有成员。

下面举个例子说明继承的使用。

        接着1.1节的程序,有一个People类,其中已经定义了name、age、speak()方法,若不想重写这个People类,现在新建一个Animal类,让People类继承Animal类,若是共用继承,则People类实例对象中就可以使用Animal类中成员了。

        在Ubuntu下新建一个06_inherit目录,在其中新建一个06_inherit.cpp文件,代码如下:

代码语言:javascript
复制
#include <iostream>
#include <string>
using namespace std;

//抽象出两个属性,各种动物都有的
class Animal
{
public:
	string sex;
	int weight;
};

//People类去继承Animal类
class People : public Animal
{
public:
	string name;
	int age;
	void speak(){
		cout << "my name is " << name << ", age is " << age << endl;
	}	
};

int main()
{
	//从栈中实例化对象
	People people;
	people.name = "小芳";
	people.age = 18;
	people.sex = "女";
	people.weight = 90;
	cout << "我的名字叫 " << people.name << ",年龄 " << people.age << ",性别 "  << people.sex << ",体重 " << people.weight << "斤" << endl;
	
	return 0;
}

编译程序运行:

3 总结

        本次博文首先是总结了C++中类和对象的基本概念,给出了构造函数和析构函数的区别,并总结了this指针的使用方法,有了以上基础后,进一步总结了C++语言的三大特征之一继承的基本概念,并结合实例演示了继承的使用方法。

作于202303072230,已归档

———————————————————————————————————

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0 引言
  • 1 类和对象
    • 1.1 类和对象基本概念 
      • 1.2 构造函数和析构函数
        • 1.3 this指针
        • 2 继承
        • 3 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档