C++面试笔记(1)

1. C和C++的区别

C++面向对象的三大特性

image

面向对象的三个基本特征:封装、继承、多态
1、封装:把客观事物封装成抽象的类,类进行信息隐藏
关键字 |当前类 |包内 |子孙类| 包外
--|--|--|--|--
public |√ |√ |√ |√
protected| √| √| √| ×
friendly| √| √| ×| ×
private| √| ×| ×| ×

2、继承:使用现有类的所有功能,并在无需编写原来的类的情况下对这些功能进行扩展
分为父类和子类
继承的过程,就是一般到特殊的过程
3、多态:允许将子类类型的指针赋值给父类类型的指针
实现多态有两种方式:

(1) 覆盖:子类重新定义父类的虚函数的做法

(2) 重载:允许存在多个同名函数,但是参数表不同
基类指针指向子类对象

作用

(1) 封装可以隐藏实现的细节,使得代码模块化

(2) 继承扩展已有的代码模块--代码复用

(3) 实现接口的重用

C语言和C++的区别
从思想上
-- C程序的的设计首先考虑的是如何听过一个过程,对输入进行运算处理得到输出,是一个结构化语言
-- C++首先考虑的是如何构造出一个对象模型,让这个模型能够契合与之对应的问题域。

C++ 与 C 的区别(细化)
***

2. 指针和引用的区别

浅谈 C++ 中指针和引用的区别

(1) 性质区别:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;
而引用跟原来的变量实质上是一个佛那个下,只不过是一个别名

(2) 指针可以多级、引用最多一级

(3) 指针可以为空、引用不能为空

(4) 指针在初始化为可以改变,引用不能

(5) sizeof(指针)=指针本身的大小 sizeof(引用)=所指向变量的大小
***

3. 野指针和悬空指针的区别

野(wild)指针与悬空(dangling)指针
野指针是指没有初始化的指针,野指针指向不可用的内存

悬空指针是指指针最初指向的内存已经被释放的一种指针
***

4. const和static之间的区别

const的作用:

(1) 修饰变量,说明该变量不可以被改变

(2) 修饰指针,分为指向常量的指针和指针常量
常量指针和指针常量

int _tmain(int argc, _TCHAR* argv[])
{
    //定义变量
    int a=1;
 
    //定义常量
    const int b=2;
 
    //定义常量指针
    const int *ptr1=&a;
 
    //定义指针常量,必须赋值
    int* const ptr2=&a;
 
    //错误,不能把常量的地址赋给指针变量
    int *ptr3=&b;
 
    //正确,可以把常量的地址赋给常量指针
    const int* ptr4=&b;
 
    //错误,间接引用常量指针不可以修改内存中的数据
    *ptr1=3;
 
    //正确,间接引用指针常量可以修改内存中的数据
    *ptr2=4;
 
    //正确,常量指针可以指向其他变量
    ptr1=&b;
 
    //错误,指针常量不可以指向其他变量
    ptr2=&b;
 
    //常量指针常量,即不可以间接引用修改内存数据,也不可以指向别的变量
    const int * const ptr5=&a;
 
    //错误,不可以间接引用修改内存数据
    *ptr5=5;
 
    //错误,不可以修改指向的对象
    ptr5=&b;
 
    return 0;
}

(3) 常量引用,经常用于形参类型,即避免了拷贝,又避免了函数对值的修改

(4) 修饰成员函数,说明该成员函数内不能修改成员变量。

// 类
class A
{
private:
    const int a;                // 常对象成员,只能在初始化列表赋值

public:
    // 构造函数
    A() { };
    A(int x) : a(x) { };        // 初始化列表

    // const可用于对重载函数的区分
    int getValue();             // 普通成员函数
    int getValue() const;       // 常成员函数,不得修改类中的任何数据成员的值
};

void function()
{
    // 对象
    A b;                        // 普通对象,可以调用全部成员函数
    const A a;                  // 常对象,只能调用常成员函数、更新常成员变量
    const A *p = &a;            // 常指针
    const A &q = a;             // 常引用

    // 指针
    char greeting[] = "Hello";
    char* p1 = greeting;                // 指针变量,指向字符数组变量
    const char* p2 = greeting;          // 指针变量,指向字符数组常量
    char* const p3 = greeting;          // 常指针,指向字符数组变量
    const char* const p4 = greeting;    // 常指针,指向字符数组常量
}

// 函数
void function1(const int Var);           // 传递过来的参数在函数内不可变
void function2(const char* Var);         // 参数指针所指内容为常量
void function3(char* const Var);         // 参数指针为常指针
void function4(const int& Var);          // 引用参数在函数内为常量

// 函数返回值
const int function5();      // 返回一个常数
const int* function6();     // 返回一个指向常量的指针变量,使用:const int *p = function6();
int* const function7();     // 返回一个指向变量的常指针,使用:int* const p = function7();

static作用

(1) 修饰普通变量,修改变量的存储区域和生命周期,使变量存储在静态区,在 main 函数运行前就分配了空间,如果有初始值就用初始值初始化它,如果没有初始值系统用默认值初始化它。

(2) 修饰普通函数,表明函数的作用范围,仅在定义该函数的文件内才能使用。在多人开发项目时,为了防止与他人命令函数重名,可以将函数定位为 static。

(3) 修饰成员变量,修饰成员变量使所有的对象只保存一个该变量,而且不需要生成对象就可以访问该成员。

(4) 修饰成员函数,修饰成员函数使得不需要生成对象就可以访问该函数,但是在 static 函数内不能访问非静态成员。

5 this指针

C++ this 指针
在C++中。每一个对象都能通过this指针来访问自己的地址,this指针是所有成员函数的隐含参数。因此在成员函数内部,它可以用来指向调用对象
其中,友元函数没有this指针,因为友员不是类的成员,只有成员函数才有this指针

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      // 构造函数定义
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      int compare(Box box)
      {
         return this->Volume() > box.Volume();
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};
 
int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2
 
   if(Box1.compare(Box2))
   {
      cout << "Box2 is smaller than Box1" <<endl;
   }
   else
   {
      cout << "Box2 is equal to or larger than Box1" <<endl;
   }
   return 0;
}

6 友元函数

类的友元函数是定义在类的外部,但有权访问类的私有和保护成员。尽管友元函数的原型在类的定义中,但是友元函数并不是成员函数
友元可以是一个函数,也可以是一个类;友元类的整个类及其所有成员都是友元
声明函数为友元:

#include <iostream>
 
using namespace std;
 
class Box
{
   double width;
public:
   friend void printWidth( Box box );
   void setWidth( double wid );
};

// 成员函数定义
void Box::setWidth( double wid )
{
    width = wid;
}

// 请注意:printWidth() 不是任何类的成员函数
void printWidth( Box box )
{
   /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
   cout << "Width of box : " << box.width <<endl;
}
 
// 程序的主函数
int main( )
{
   Box box;
 
   // 使用成员函数设置宽度
   box.setWidth(10.0);
   
   // 使用友元函数输出宽度
   printWidth( box );
 
   return 0;
}

7. struct与class之间的区别

C++ 中结构体与类的区别

(1) 默认的访问控制:struct是public class是private

(2) Class还能用于定义模板参数,而struct不用于定义模板参数
struct更适合看成一个数据结构的实现体,class更适合看成是一个对象的实现体
***

8. 常见数据结构在32位和64位机器上的字节数

/ 32位 64位
char 1 1
指针变量 4 8
short 2 2
int 4 4
uint 4 4
float 4 4
double 8 8
long 4 8
long long 8 8
ulong long 4 8

9.虚函数可以inline吗?

引入inline的原因?

在 c/c++ 中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表示为内联函数。

栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。

在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足而导致程序出错的问题,如,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。

类中除了虚函数的其他函数都会自动隐式地当成内联函数

(1) 虚函数是可以内联的,但是当虚函数表现多态时不能内联

(2) 内联是在编译器建议编译器内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。

(3) inline virtual 唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 Base::who()),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。

虚函数内联使用:

#include <iostream>  
using namespace std;
class Base
{
public:
    inline virtual void who()
    {
        cout << "I am Base\n";
    }
    virtual ~Base() {}
};
class Derived : public Base
{
public:
    inline void who()  // 不写inline时隐式内联
    {
        cout << "I am Derived\n";
    }
};

int main()
{
    // 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。 
    Base b;
    b.who();

    // 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。  
    Base *ptr = new Derived();
    ptr->who();

    // 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。
    delete ptr;
    ptr = nullptr;

    system("pause");
    return 0;
} 

10 volatile关键字

C/C++ 中 volatile 关键字详解
谈谈 C/C++ 中的 volatile
***

猜你喜欢

转载自www.cnblogs.com/jeremy0426/p/9509382.html