首页 > 其他分享 >cpp面向对象(类的成员、构造函数、析构函数)

cpp面向对象(类的成员、构造函数、析构函数)

时间:2023-12-30 22:12:28浏览次数:37  
标签:调用 const 函数 成员 析构 cpp 构造函数

class/struct

在cpp面向对象编程中,一般使用class来作为OOP的载体,而将struct仅作为类型的一个集合。虽然这两者在功能上基本没有差异,除了class的默认访问控制是private,而struct的是public的。

类的成员

类作用域

类本身是一个作用域,我们可以在类内声明一个函数/变量,并且用类名::函数名的方式在类外定义它。

特别的,对于类的静态变量而言,我们必须这么做。

静态成员

对于类来说,静态成员并不依赖于类的实例而存在,也就是说,它的静态成员会存在于整个程序的执行过程中,直到程序结束。因此,类的所有实例可以通过类名::成员名的方式来共享类的所有静态成员,且静态函数只能调用静态成员。

const成员函数

如果一个类指针是const的,那么它不能修改这个类中的任何成员变量。

如果成员函数在参数列表之后紧跟着一个const,表示这是一个常量成员函数,默认情况下,this是一个指向非常量类型的常量指针(可以看作是const在后的指针),这里const的作用是修改隐式this指针的类型,使其变成一个指向常量的指针。

构造函数

如果我们使用new运算符新建一个对象,那么它首先会调用malloc分配内存,然后调用构造函数创建这个对象。

如果类有继承层次,那么首先执行基类的构造函数,再执行派生类的。cpp没有super关键字,也就是说,我们无需在派生类的构造函数中显式的调用基类构造函数,这个调用关系由编译器来管理。

构造函数不能是const:显然类内成员需要初始化

构造函数不能是virtual:

  1. 对象创建时,虚表还没有构造完成
  2. 构造函数有其调用次序,virtual显然会破坏这种原则

每个类都有一个默认的构造函数,自定义构造函数会覆盖默认的构造函数,如果我们需要保留默认构造函数,则可以将其声明为default:A() = default

构造函数必须是public的,但不能通过类指针进行调用。

初始值列表构造函数:很方便的一种赋初值形式,甚至可以在赋完初值后再执行一些额外的操作

class A {
  int x;
  double y;
  char z;
public:
  A(int a, double b, char c) : x(a), y(b), z(c) {}
};

委托构造

允许一个构造函数调用另一个构造函数,例如:

class A {
public:
  A() : A(0) {}
  A(int x) { std::cout << x << std::endl; }
}

这样,第一个构造函数就调用了第二个构造函数。

拷贝构造

拷贝构造函数默认只一一复制非静态成员。

原型:A(const A& other),有以下四种场景会触发:

  1. 用一个对象初始化另一个对象时,如A x; A y = x
  2. 通过值进行传参
  3. 通过值返回对象
  4. 用花括号列表初始化类成员

拷贝赋值运算符

实际上是重载赋值号,和拷贝构造的区别是,被赋值的对象是已经创建好的。原型:A& operator=(const A& other)

移动构造

原型:A(const A&& other)

移动赋值运算符

原型:A& operator=(const A&& other)

析构函数

与构造函数正好相反,先派生类后基类。

基类的析构函数需要声明为虚函数,考虑以下场景:

Base* ptr = new Derived();
delete ptr;

执行delete ptr;时,如果基类的析构函数非虚,采用静态绑定方式,会直接调用Base类的析构函数。

如果基类的析构函数为虚,那么编译器看到虚函数会采用动态绑定方式,发现指针指向的类型实际上是Derived,由于Derived类的析构函数重写了Base类的析构函数(为什么不同名能重写,问就是特性),而且Derived的析构函数调用完成后会默认调用Base的析构函数,这样就实现了正常的资源释放。

析构函数一般不显式调用,一种特例是使用placement new(一种可以在自己申请的内存上创建对象的方法)创建对象时,由于对象不一定在堆空间上,此时不能调用delete释放资源,而需要手动调用析构函数。

标签:调用,const,函数,成员,析构,cpp,构造函数
From: https://www.cnblogs.com/DGJG/p/17936912

相关文章

  • auto{x}与auto(x)---一位中国小伙为cppreference作出的贡献
      C++作为一门静态类型语言,是需要程序员声明变量类型的。然而来到了C++11,auto的诞生使得变量声明变得及为方便,尤其是对于比较长的模板类型,auto一定程度上为代码编写者减轻了负担。到了C++23,突然来了个新特性:auto{x}/auto(x),这又是个什么东西,它的motivation又是什么?   首先......
  • 【Cpp 语言基础】 string 类型进阶使用
    大纲:1.特殊的初始化方式2.获取子串3.与<algorith>中对应的成员函数 ”串“类型类似于数组类型(C语言的字符串就是字符数组)。但是有一点不同之处,就是串经常作为一个整体才有实际的”意义“,而数组每个单元都有其”意义“。因此,“串”的操作中,很大部分是“串”的整体、局部......
  • cpp取系统时钟
    //test.cpp:定义控制台应用程序的入口点。//#pragmawarning(disable:4996)#include"stdafx.h"#include"time.h"#include"windows.h"#include<iostream>usingnamespacestd;void取系统时间(){ time_ttimer;//time_t实际是int64 str......
  • 【Cpp 语言基础】vector像数组一样地初始化多个元素
    一般的vector的初始化有两种方式,push_back和(n,val)方式vector<int>vect;//一般方式vect.push_back(10);vect.push_back(20);//Createavectorofsizenwith//allvaluesas10.vector<int>vect(n,10);但是也可以像C语言的数组一样初始化://方式3:直接像数组一......
  • C++基础 -12- 类的析构函数
    ———————标准输入输出——————— ......
  • CPP创建子线程
     #include<iostream>#include<thread>usingnamespacestd;structMyStruct{inta=0;strings="abc雷";};//线程入口voidproc(MyStruct&a){for(intm=0;m<50;m++){if(a.a==0)......
  • [C++从入门到精通] 10.回顾类内初始化、默认构造函数、=default
    ......
  • cpp-strtok-s
    title:strtok_s()函数用法author:TokisakiGalaxytop:falsecover:falsetoc:truecomments:truemathjax:falsenoindex:falsesitemap:truedate:2020-08-2818:34:18img:coverImg:excerpt:strtok_s()函数用法tags:-C++categories:-编程password:当......
  • cpp-opt-mysql
    title:c++操作mysql数据库author:TokisakiGalaxytop:falsecover:falsetoc:truecomments:truemathjax:falsenoindex:falsesitemap:truedate:2020-09-1214:17:04img:coverImg:excerpt:C++操作mysql数据库tags:-C++-mysqlcategories:-编程pas......
  • cpp-Array-element-count
    title:C++数组元素个数计算author:TokisakiGalaxytop:falsecover:falsetoc:truemathjax:falsedate:2019-12-03img:coverImg:excerpt:C++数组元素个数计算tags:-C++categories:-编程password:inti_max(inta[]){ inttmp=a[0]; for(inti=......