C++面试常见问题整理汇总
本文旨在整理和汇总C++面试中常见的问题,包括但不限于基础知识、语法、实际应用等方面,并提供相应的解答和说明以供参考。
1. 基础知识
1.1 C++的数据类型有哪些?它们所占用的字节空间分别是多少?
C++的数据类型包括基本数据类型和构造类型,其中基本数据类型有:
- 整型(int、short、long、long long等)
- 布尔型(bool)
- 字符型(char)
- 浮点型(float、double)
构造类型有:
- 数组
- 函数
- 指针
- 引用
- 结构体
- 枚举
- 类
它们所占用的字节空间会根据具体的编译器、操作系统或平台而有所不同。
1.2 C++的static关键字有什么作用?
static
关键字可以用于以下几个方面:
- 修饰全局变量,使其在文件内可见,避免与其他文件的同名变量发生冲突;
- 修饰局部变量,使其只被初始化一次并保留其值,在函数调用之间互不干扰;
- 修饰成员函数,使其成为该类的静态成员函数,可以通过类名直接调用而无需创建对象实例;
- 修饰类的成员变量,使其成为该类的静态成员变量,所有类的实例共享同一个静态成员变量,而不是每个实例都拥有一个副本。
示例说明
示例1
static const int max_num = 100;
在该示例中,max_num
被定义为一个静态的常量整型变量,且只能在本文件内使用。由于它被定义为常量,因此不管如何修改,其初始值始终为100。
示例2
void test_static_variable()
{
static int count = 0;
count++;
cout << "count: " << count << endl;
}
int main()
{
for (int i = 0; i < 5; i++)
{
test_static_variable();
}
return 0;
}
在该示例中,test_static_variable
函数中的count
变量被定义为静态的局部变量,即只被初始化一次,之后每次进入函数都会保留其之前的值。因此,上述程序将输出:
count: 1
count: 2
count: 3
count: 4
count: 5
2. 语法问题
2.1 C++中的类型转换有哪几种?它们的作用分别是什么?
C++中的类型转换包括以下几种:
- C风格类型转换:
(type)value
,将一个值强制转换为指定类型的值,容易引起类型不匹配的问题; - 函数风格类型转换:
type(value)
,使用类型转换运算符重载函数,可以避免类型不匹配的问题; static_cast
强制类型转换:static_cast<type>(value)
,适用于各种基本数据类型之间的转换,不安全的转换将在编译时被检测出来;dynamic_cast
动态类型转换:dynamic_cast<type>(expression)
,用于将基类指针或引用转换为派生类指针或引用,与static_cast
不同的地方在于dynamic_cast
会在运行时检测是否可以安全地转换;reinterpret_cast
重新解释类型转换:reinterpret_cast<type>(value)
,适用于各种指针类型之间的转换,但危险性较高,不应该轻易使用;const_cast
去除常量属性转换:const_cast<type>(value)
,用于去除指针或引用的const或volatile属性。
2.2 什么是虚函数?为什么要使用虚函数?
虚函数是在基类中使用virtual
关键字声明的成员函数,它的特点是可以在派生类中进行重写,即在派生类中定义与基类虚函数具有相同名称、返回类型和参数列表的函数,从而实现多态性。
使用虚函数的原因在于,通过派生类对虚函数进行重写,可以实现对基类指针或引用指向的派生类对象的不同动态行为,增强了程序的灵活性和可扩展性。
示例说明
示例1
class A
{
public:
virtual ~A() {}
virtual void print() const { cout << "class A" << endl; }
};
class B : public A
{
public:
virtual void print() const { cout << "class B" << endl; }
};
class C : public B
{
public:
virtual void print() const { cout << "class C" << endl; }
};
int main()
{
A* a1 = new A();
a1->print(); // 输出class A
A* a2 = new B();
a2->print(); // 输出class B
A* a3 = new C();
a3->print(); // 输出class C
return 0;
}
在该示例中,类B和类C均继承了类A,并在其中重定义了虚函数print,分别输出"class B"和"class C"。在主函数中,可以看到,当基类指针a指向派生类对象B时,执行print函数时却输出了"class B",而当基类指针a指向派生类对象C时,执行print函数时却输出了"class C"。这就是基于多态性的结果,可以看到在程序运行过程中其表现出了不同的行为。
示例2
class Base
{
public:
void do_something() { do_internal(); }
private:
virtual void do_internal() { cout << "do something base" << endl; }
};
class Derived : public Base
{
private:
virtual void do_internal() { cout << "do something derived" << endl; }
};
int main()
{
Base* b = new Derived();
b->do_something();
return 0;
}
在该示例中,基类Base中定义了一个do_something函数和该函数的实现函数do_internal,并在实现函数中调用了do_internal函数。在派生类Derived中重载do_internal函数并输出"do something derived"。在主函数中定义了一个基类指针b,其指向派生类对象Derived。当执行b->do_something()时,实际上调用的是派生类中重载的do_internal函数,其输出"do something derived"。这说明当我们使用基类指针或引用时,虚函数会自动根据实际指向的派生类对象而被调用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++面试常见问题整理汇总 - Python技术站