C++基础知识第三天(面试必备)

简介:   1.struct 的区别(C 和 C++):  C语言中只能定义变量。  C++语言中可以定义变量和函数。同时C++语言中,struct 中所有变量和函数都是 "public" 权限  2.类的封装:  3.类内部的三种权限  public:共有属性(修饰的成员变量和方法; 可以在类的内部和外部使用。)  private:私有属性(修饰的成员变量和方法,只能在类的内部使用,不能在类的外部使用)  protected:主要用于继承,保护属性(修饰的成员变量和方法; 可以在类的内部和继承的子类使用,不能在类的外部使用)  4.struct 和 class 的区别

  1.struct 的区别(C 和 C++):

  C语言中只能定义变量。

  C++语言中可以定义变量和函数。同时C++语言中,struct 中所有变量和函数都是 "public" 权限

  2.类的封装:

  3.类内部的三种权限

  public:共有属性(修饰的成员变量和方法; 可以在类的内部和外部使用。)

  private:私有属性(修饰的成员变量和方法,只能在类的内部使用,不能在类的外部使用)

  protected:主要用于继承,保护属性(修饰的成员变量和方法; 可以在类的内部和继承的子类使用,不能在类的外部使用)

  4.struct 和 class 的区别:

  struct 中成员的默认权限为 public;

  class 中成员的默认权限为 private;

  5.类的调用(一个类调另一个类)

  6.对象的构造和析构;

  1)构造函数:"名称和类名相同";"没有返回值 "。"可以有多个,进行函数重载"

  在内存开辟之后调用构造函数。

  2)无参构造函数和有参构造函数(又分为两种)

  1.无参构造函数:定义对象的时候,对象后不能加括号。如:class stu{ stu(){"无参构造函数"}}; stu st;(正确定义对象)。

  如果加上括号: stu st(); 编译的时候不会报错,(因为编译器把它当作函数声明),运行的时候会报错。

  2.有参构造函数:

  "普通参数": 根据形参的类型和个数,也可以进行函数重载。

  class Animal{

  public:

  Animal(int age)

  {

  cout << "一个参数构造函数数字!" << endl;

  mName="undefined";

  mAge=age;

  }

  Animal(string name)

  {

  cout << "一个参数构造函数字母!" << endl;

  mName=name;

  mAge=0;

  }

  Animal(string name,int age)

  {

  cout << "两个参数构造函数!" << endl;

  mName=name;

  mAge=age;

  }

  //拷贝(复制)构造函数 用一个对象来初始化另一个对象

  Animal(const Animal& animal)

  { //拷贝构造函数,形参必须是引用。否则会造成死循环,一直调用它本身。本质上成了递归调用本身。

  cout << "拷贝构造函数!" << endl;

  mName=animal.mName;

  mAge=animal.mAge;

  }

  "拷贝参数":用一个对象来初始化另一个对象

  它的形参必须是引用。如果是普通变量,就会造成本质上的递归调用本身;无意义。

  3)析构函数:"名称=类名+"~""; "没有返回值";"没有游戏参数"。"一个类只可以有一个析构函数"

  在内存释放之前调用析构函数。

  7.构造函数调用规则: (参考上面的代码)

  1) 括号法;

  Animal animal1("smith"); //一个参数构造函数字母!

  Animal animal2(20); //一个参数构造函数数字!

  Animal animal3("John",30); //两个参数构造函数!

  Animal animal4(animal3); //拷贝构造

  2)显示调用构造函数(匿名对象调用拷贝构造的问题)

  Animal("Smith",30); //匿名函数生命周期仅限于当前行;此行运行完后立即析构。

  Animal animal5=Animal(30); // 一个参数构造函数数字!;形参为普通变量

  Animal animal5=Animal("smith",90); 注意:/"两个参数构造函数!;拷贝构造。这行比上一行多了一个拷贝构造,是因为string容器的缘故。只有这时才会有拷贝构造"

  Animal animal5(animal(30)); //一个参数构造自考函数数字!。

  Animal animal5(animal(30,"smith")); "两个参数构造函数!;拷贝构造。" 原因同上,当不调用 string 参数时,它不会调用拷贝构造。"是由编译器处理的,具体处理方式不清楚"

  "上面那两种情况,调不调用拷贝构造函数,主要看参数类型。===有string:就调拷贝构造函数;====没有string: 就不调拷贝构造函数===="

  匿名对象如果有变量来接,它就是一个对象;"此时这个变量就相当于匿名对象的名称。"

  匿名对象如果没有变量来接,他就是一个实例化对象。

  Animal4("john",92); Animal(animal4); 此时当这两句在一起,编译器会报错,重定义。

  3)等号法

  Animal animal5=10; //不常用。调用一个函数构造函数

  Animal animal5=animal4l; “拷贝构造,常用

  8.拷贝构造常用的两种调用方式:

  Animal animal5=animal4l;

  Animal animal5(animal4l);

  9.拷贝构造的调用时机:

  1)对象以值传递的方式传递给函数参数。 void func(Animal animal2){ }; 用实参初始化形参,调用了拷贝构造函数

  2)用一个对象初始化另一个对象。Animal animal5=animal4l; 或者:Animal animal5(animal4l);

  3)函数返回局部对象。(注意这里:debug模式 和release模式不一样)。

  debug模式下:会调用拷贝构造,打印两个地址也不相同。

  release模式下,不会调用拷贝构造,打印的地址相同,编译器这里做了优化,直接把原来的对象返回回去了。

  Animal MyBussiness()

  {

  //局部对象

  Animal animal; //无参构造

  cout << &animal << endl;

  return animal; //编译器先拷贝一份,然后返回。相当于返回一个匿名对象

  }

  void test03()

  {

  Animal animal=MyBussiness();

  cout << &animal << endl;

  }

  10.构造函数调用规则:

  默认情况下,编译器至少为我们写的类增加三个函数

  1)默认构造函数(无参,函数体为空)

  默认析构函数(无参,函数体为空)

  默认拷贝构造函数,对类中非静态成员属性简单 "值"拷贝。

  2) 如果用户定义了"拷贝构造函数",C++不会再提供"任何默认构造函数"。

  3)如果用户定义了"普通构造,"C++"不会"再提供"默认无参构造",但是"会提供默认拷贝构造"。

  4)在构造函数中调用构造函数是一个危险的行为。本质上:里面的构造函数相当于一个"匿名对象"。生命周期只有本行(没有变量接的情况下)。

  11.初始化列表:初始化成员列表只能在构造函数使用。

  "构造函数的初始化列表顺序:"

  1)当一个类中组合了其他类的对象,先执行被组合的构造函数。

  2)如果组合对象有多个,来自不同的类,根据定义的顺序进行构造函数的调用,而不是初始化列表的顺序。

  3)“被组合对象的构造顺序:与定义顺序有关系,与初始化列表的顺序,没有关系”

  4)若类成员中有 const 修饰,必须在对象初始化的时候,给 const 元素初始化。此时就用到了"初始化列表"。

  "析构函数:与构造函数的调用顺序相反。"

  12.深拷贝和浅拷贝

  class Person

  {

  public:

  Person(int a, int b) :_b(b),_a(b){} "初始化列表"

  "深拷贝"

  Person(const Person &p1)

  {

  mstr=(char *)malloc(strlen(p1.mstr) + 1); "核心步骤" “会进行内存拷贝”

  strcpy(mstr, p1.mstr);

  _a=p1._a;

  _b=p1._b;

  }

  "浅拷贝"

  Person(const Person &p1)

  {

  mstr=p1.mstr; "这里只会把一个对象的指针地址,赋给另一个对象的指针。";“不会进行内存拷贝”

  _a=p1._a;

  _b=p1._b;

  }

  void print_func()

  {

  cout << _a <<" " << _b << endl;

  }

  private:

  int _a;

  int _b;

  char *mstr;

  };

  13.C++中 string 是一个类。

  14.已知一个Print类,在该类的main()函数里执行语句 "Print a, b[2], *c;" 后;程序会自动调用该类的构造函数 4 次。

  a会调用一次;b会调用两次;*c是空指针,没有开辟空间不会调用。

目录
相关文章
|
2月前
|
存储 算法 编译器
C++面试题其一
C++文件编译与执行的四个阶段 预处理:处理#include、#define等预处理指令。 编译:将源码翻译为目标代码。 汇编:将目标代码转换为机器指令。 链接:将目标文件和库文件合并生成可执行文件。 STL中的vector的实现,是怎么扩容的? vector通过动态数组实现,当容量不足时,分配更大的内存(通常是原来的两倍),复制旧数据到新内存,并释放旧内存。
55 2
|
2月前
|
存储 程序员 编译器
C++面试题其二
extern "C" 用于告诉编译器按照C语言的链接方式处理代码,通常用于C++代码与C代码混合编程,以防止因名字修饰(name mangling)引起的链接错误。例如: extern "C" { void c_function(); } 通过这些问题的深入理解和解答,能够更好地掌握C++编程的核心概念和实际应用,为面试做好充分的准备。
51 1
|
1月前
|
C语言 C++ 开发者
C++基础知识(一:命名空间的各种使用方法)
C++在C的基础上引入了更多的元素,例如类,类的私密性要比C中的结构体更加优秀,引用,重载,命名空间,以及STL库,模板编程和更多的函数,在面向对象的编程上更加高效。C语言的优势则是更加底层,编译速度会更快,在编写内核时大多数都是C语言去写。 在C++中,命名空间(Namespace)是一种组织代码的方式,主要用于解决全局变量、函数或类的命名冲突问题。命名空间提供了一种封装机制,允许开发者将相关的类、函数、变量等放在一个逻辑上封闭的区域中,这样相同的名字在不同的命名空间中可以共存,而不会相互干扰。
|
2月前
|
存储 网络协议 编译器
【干货总结】Linux C/C++面试知识点
Linux C/C++基础与进阶知识点,不仅用于面试,平时开发也用得上!
484 10
|
1月前
|
C++
C++基础知识(二:引用和new delete)
引用是C++中的一种复合类型,它是某个已存在变量的别名,也就是说引用不是独立的实体,它只是为已存在的变量取了一个新名字。一旦引用被初始化为某个变量,就不能改变引用到另一个变量。引用的主要用途包括函数参数传递、操作符重载等,它可以避免复制大对象的开销,并且使得代码更加直观易读。
|
1月前
|
算法 编译器 C++
C++基础知识(三:哑元和内联函数和函数重载)
在C++编程中,"哑元"这个术语虽然不常用,但可以理解为在函数定义或调用中使用的没有实际功能、仅作为占位符的参数。这种做法多见于模板编程或者为了匹配函数签名等场景。例如,在实现某些通用算法时,可能需要一个特定数量的参数来满足编译器要求,即使在特定情况下某些参数并不参与计算,这些参数就可以被视为哑元。
|
1月前
|
C++
C++基础知识(四:类的学习)
类指的就是对同一类对象,把所有的属性都封装起来,你也可以把类看成一个高级版的结构体。
|
1月前
|
自然语言处理 程序员 C++
C++基础知识(五:运算符重载)
运算符重载是C++中的一项强大特性,它允许程序员为自定义类型(如类或结构体)重新定义标准运算符的行为,使得这些运算符能够适用于自定义类型的操作。这样做可以增强代码的可读性和表达力,使得代码更接近自然语言,同时保持了面向对象编程的封装性。
|
1月前
|
存储 编译器 C++
C++基础知识(六:继承)
多态是面向对象编程的四大基本原则之一,它让程序能够以统一的接口处理不同的对象类型,从而实现了接口与实现分离,提高了代码的灵活性和复用性。多态主要体现在两个层面:静态多态(编译时多态,如函数重载)和动态多态(运行时多态,主要通过虚函数实现)。
|
1月前
|
存储 编译器 C++
C++基础知识(七:多态)
多态是面向对象编程的四大基本原则之一,它让程序能够以统一的接口处理不同的对象类型,从而实现了接口与实现分离,提高了代码的灵活性和复用性。多态主要体现在两个层面:静态多态(编译时多态,如函数重载)和动态多态(运行时多态,主要通过虚函数实现)。