【C++】构造函数、析构函数和继承

文章讲述了C++中的构造函数用于对象实例化时初始化成员变量,如使用默认构造函数或带参数的构造函数。析构函数在对象销毁时执行,用于清理资源,防止内存泄漏。此外,文章还讨论了继承的概念,如何通过继承减少代码重复,并实现多态性,以及重载允许改变基类行为的能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++构造函数

构造函数是一种特殊类型的方法,在每次实例化对象时运行

实例化

例1

class Entity
{
public:
 float X, Y;

 void Print()
 {
  std::cout << X << ", " << Y << std::endl;
 }
};
int main()
{
 Entity e;
 e.Print();
 std::cin.get();
}

得到0, 4.56996e-039

  • 当实例化Entity,并给他们分配内存时,并没有初始化那个内存,即我们得到了那个内存原来存在的东西
  • 我们希望默认初始化为0

手动打印X和Y的话,则会报错没有初始化局部变量:

std::cout << e.X << e.Y << std::endl;

所以,我们需要一种方法,当构造Entity实例化的时候,想把X和Y初始化为0

初始化函数

例3

#include <iostream>


class Entity
{
public:
 float X, Y;

 void Init()
 {
  X = 0.0f;
  Y = 0.0f;

 }

 void Print()
 {
  std::cout << X << ", " << Y << std::endl;
 }
};
int main()
{
 Entity e;
 e.Init();
 std::cout << e.X << ", " << e.Y << std::endl;
 e.Print();
 std::cin.get();
}

然而,这种方法每次都需要调用初始化函数Init(),有没有一种方法,创建对象的同时就可以对其进行初始化

构造函数

构造函数是一种特殊类型的方法,每次构造对象时都会调用的方法

例4

#include <iostream>


class Entity
{
public:
 float X, Y;
 Entity()
 {
  X = 0.0f;
  Y = 0.0f;
 }

 void Print()
 {
  std::cout << X << ", " << Y << std::endl;
 }
};
int main()
{
 Entity e;
 std::cout << e.X << ", " << e.Y << std::endl;
 e.Print();
 std::cin.get();
}

实际上,不需要指定构造函数,默认就会有一个构造函数,但这个构造函数其实什么都没做,类似这样:

Entity()
 {
 }

带参数的构造函数

例5

#include <iostream>


class Entity
{
public:
 float X, Y;
 Entity()
 {
  X = 0.0f;
  Y = 0.0f;
 }
 Entity(float x, float y)
 {
  X = x;
  Y = y;

 }

 void Print()
 {
  std::cout << X << ", " << Y << std::endl;
 }
};
int main()
{
 Entity e(10.0f, 5.0f);
 e.Print();
 std::cin.get();
}
  • 如果不实例化对象,将不会运行构造函数,所以如果使用一个类的静态方法,将不会运行构造函数
  • 当用new关键字并创建一个对象实例,也会调用构造函数

删除构造函数

例6

class Log
{
public:
 static void Write()
 {

 }
};

如果只想以这种方式使用类:

int main()
{
 Log::Write();
}

而不想实例化对象:

int main()
{
 Log l;

}
  1. 可以通过private来隐藏构造函数
class Log
{
private:
 Log() {}
public:
 static void Write()
 {

 }
};
  1. 也可以用delete:
class Log
{

public:
 Log() = delete;

 static void Write()
 {

 }
};

C++析构函数

  • 在销毁对象时运行,只要对象要被销毁,析构函数就会调用
  • 构造函数的功能通常是设置变量或者做任何需要的初始化
  • 析构函数的功能则是卸载变量,并清理使用过的内存
  • 析构函数同时适用于栈和堆分配的对象,如果使用new分配一个堆对象,当调用delete时,析构函数会被调用;而如果只是一个栈对象,当作用域结束时,栈对象就被删除

析构函数

例7

class Entity
{
public:
 float X, Y;
 // 构造函数
 Entity()
 {
  X = 0.0f;
  Y = 0.0f;

  std::cout << "Created Entity" << std::endl;
 }
 Entity(float x, float y)
 {
  X = x;
  Y = y;

 }
 // 析构函数
 ~Entity()
 {
  std::cout << "Destroyed Entity!" << std::endl;

 }

 void Print()
 {
  std::cout << X << ", " << Y << std::endl;
 }
};

void Function()
{
 Entity e;
 e.Print();
}
int main()
{
 Function();

 std::cin.get();

}

在函数作用域结束时,由于对象是在栈上创建的,所以当函数作用域结束时,对象就被销毁

为什么需要析构函数

  • 因为如果在构造函数中调用了特定的初始化代码,需要在析构函数中,卸载或销毁所有东西,不然会造成内存泄漏
  • 如果是堆上分配的对象,则需要手动清理堆上的内存

C++继承

  • 继承允许我们有一个相互关联的类的层次结构
  • 继承允许我们有一个包含公共功能的基类
  • 继承允许从那个基类中分离出来,从最初的父类中创建子类
  • 类、继承如此有用是因为可以帮助我们避免代码重复
  • 可以把类之间的所有公共功能放在一个父类,然后从基类(父类)创建(派生)一些类,稍微改变下功能,或者引入全新的功能

继承

例7

class Entity
{
public:
 float X, Y;

 void Move(float xa, float ya)
 {
  X += xa;
  Y += ya;

 }
};

class Player
{
public:
 const char* Name;

 float X, Y;

 void Move(float xa, float ya)
 {
  X += xa;
  Y += ya;

 }

};

Player有许多重复的代码,但跟Entity又有点不同,可以使用继承:

class Player: public Entity
{
public:
 const char* Name;
 void PrintName()
 {
  std::cout << Name << std::endl;
 }

};
int main()
{
 Player player;
 player.Move(5, 5); 
 player.X = 5;

 std::cin.get();

}
  • 任何在Entity类中不是私有的东西,实际上都可以被Player访问
  • 继承可以扩展现有类,并为基类提供新功能的一种方式
  • 打印父类的大小: std::cout << sizeof(Entity) << std::endl;
  • 打印子类的大小: std::cout << sizeof(Player) << std::endl;
  • 如果Player没有扩展Enity,则Player只有const char * Name,只有四字节的内存
  • 如果Player扩展了Entity,所以Player有4+4+4=12字节的内存
  • 类的大小和内存可以发生变化,如果开始重写函数和Player类,那么需要维护V表(虚函数表),也就是要额外的内存

多态

  • 多态是一个单一类型,但有多个类型的意思
  • Player不仅是Player类型,也是一个Entity
  • 意味着我们可以在任何想要使用Entity的地方使用Player;
  • 父类是子类的子集

重载

  • 可以改变父类或基类的行为
  • 重写一个方法,并给新的代码来代替父类方法的运行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值