📅  最后修改于: 2020-10-21 05:50:01             🧑  作者: Mango
下面列出了最常见的C++面试问题和答案。
C++是由Bjarne Stroustrup创建的一种面向对象的编程语言。它于1985年发布。
C++是C的超集,主要增加了C语言中的类。
最初,Stroustrup将新语言称为“带有类的C”。但是,一段时间后,名称更改为C++。 C++的思想来自C增量运算符++。
C++不仅维护了C语言的所有方面,还简化了内存管理并添加了以下功能:
以下是C和C++之间的区别:
C | C++ |
---|---|
C language was developed by Dennis Ritchie. | C++ language was developed by Bjarne Stroustrup. |
C is a structured programming language. | C++ supports both structural and object-oriented programming language. |
C is a subset of C++. | C++ is a superset of C. |
In C language, data and functions are the free entities. | In the C++ language, both data and functions are encapsulated together in the form of a project. |
C does not support the data hiding. Therefore, the data can be used by the outside world. | C++ supports data hiding. Therefore, the data cannot be accessed by the outside world. |
C supports neither function nor operator overloading. | C++ supports both function and operator overloading. |
In C, the function cannot be implemented inside the structures. | In the C++, the function can be implemented inside the structures. |
Reference variables are not supported in C language. | C++ supports the reference variables. |
C language does not support the virtual and friend functions. | C++ supports both virtual and friend functions. |
In C, scanf() and printf() are mainly used for input/output. | C++ mainly uses stream cin and cout to perform input and output operations. |
以下是引用和指针之间的区别:
Reference | Pointer |
---|---|
Reference behaves like an alias for an existing variable, i.e., it is a temporary variable. | The pointer is a variable which stores the address of a variable. |
Reference variable does not require any indirection operator to access the value. A reference variable can be used directly to access the value. | Pointer variable requires an indirection operator to access the value of a variable. |
Once the reference variable is assigned, then it cannot be reassigned with different address values. | The pointer variable is an independent variable means that it can be reassigned to point to different objects. |
A null value cannot be assigned to the reference variable. | A null value can be assigned to the reference variable. |
It is necessary to initialize the variable at the time of declaration. | It is not necessary to initialize the variable at the time of declaration. |
该类是用户定义的数据类型。该类用关键字class声明。该类包含数据成员,其成员函数由三个修饰符定义的成员函数是私有,公共和受保护的。该类定义事物类别的类型定义。它定义了一个数据类型,但没有定义数据,仅指定了数据结构。
您可以从一个类中创建N个对象。
C++中的各种OOPS概念是:
该类是用户定义的数据类型,用于定义其属性和功能。例如,人类是一类。人的身体部位就是其属性,身体部位所执行的动作称为功能。该类不占用任何内存空间。因此,可以说类是数据的唯一逻辑表示。
声明类的语法:
class student
{
//data members;
//Member functions
}
对象是运行时实体。对象是类的实例。一个对象可以代表一个人,一个地方或任何其他项目。一个对象可以同时作用于数据成员和成员函数。该类不占用任何内存空间。使用new关键字创建对象时,将为堆中的变量分配空间,并且起始地址存储在堆栈存储器中。当创建没有新关键字的对象时,则不会在堆内存中分配空间,并且该对象在堆栈中包含空值。
class Student
{
//data members;
//Member functions
}
声明对象的语法:
Student s = new Student();
继承提供了可重用性。可重用性意味着可以使用现有类的功能。它消除了代码的冗余。继承是从旧类派生新类的技术。旧的类称为基类,新的类称为派生类。
句法
class derived_class :: visibility-mode base_class;
注意:可见性模式可以是公共,私有,受保护的。
封装是一种将数据成员和成员函数包装在单个单元中的技术。它将数据绑定到一个类中,并且没有外部方法可以访问该数据。如果数据成员是私有的,则成员函数只能访问数据。
抽象是仅显示基本细节而不表示实现细节的技术。如果成员是用public关键字定义的,则这些成员也可以在外部访问。如果成员是使用private关键字定义的,则外部方法无法访问这些成员。
数据绑定是绑定应用程序UI和业务逻辑的过程。业务逻辑中的任何更改将直接反映到应用程序UI。
多态性是指多种形式。具有相同的名称,但具有不同功能的多个函数多态性手段。多态性有两种类型:
多态:多态是指多种形式。这意味着具有相同函数的名称,但具有不同功能的多个函数。
多态性有两种类型:
运行时多态也称为动态多态。函数覆盖是运行时多态性的一个示例。函数覆盖意味着子类包含父类中已经存在的方法。因此,子类将覆盖父类的方法。在重写函数的情况下,父类和子类都包含具有不同定义的相同函数。在运行时确定对函数的调用称为运行时多态。
让我们通过一个例子来理解这一点:
#include
using namespace std;
class Base
{
public:
virtual void show()
{
cout<<"javaTpoint";
}
};
class Derived:public Base
{
public:
void show()
{
cout<<"javaTpoint tutorial";
}
};
int main()
{
Base* b;
Derived d;
b=&d;
b->show();
return 0;
}
输出:
javaTpoint tutorial
编译时多态也称为静态多态。在编译时实现的多态被称为编译时多态。方法重载是编译时多态性的一个示例。
方法重载:方法重载是一种技术,它可以让你有一个以上的函数具有相同函数的名称,但具有不同的功能。
方法重载可能基于以下原因:
让我们通过一个例子来理解这一点:
#include
using namespace std;
class Multiply
{
public:
int mul(int a,int b)
{
return(a*b);
}
int mul(int a,int b,int c)
{
return(a*b*c);
}
};
int main()
{
Multiply multi;
int res1,res2;
res1=multi.mul(2,3);
res2=multi.mul(2,3,4);
cout<<"\n";
cout<
输出:
6
24
namespace namespace_name
{
//body of namespace;
}
访问名称空间变量的语法:
namespace_name::member_name;
让我们通过一个例子来理解这一点:
#include
using namespace std;
namespace addition
{
int a=5;
int b=5;
int add()
{
return(a+b);
}
}
int main() {
int result;
result=addition::add();
cout<
输出:
10
C++中的令牌可以是关键字,标识符,字面量,常量和符号。
Bjarne Stroustrup。
以下是可以对指针执行的操作:
增量指针有两种类型:
1.预递增指针:预递增运算符将操作数递增1,表达式的值成为递增后的结果值。假设ptr是一个指针,则预递增指针表示为++ ptr。
让我们通过一个例子来理解这一点:
#include
using namespace std;
int main()
{
int a[5]={1,2,3,4,5};
int *ptr;
ptr=&a[0];
cout<<"Value of *ptr is : "<<*ptr<<"\n";
cout<<"Value of *++ptr : "<<*++ptr;
return 0;
}
输出:
Value of *ptr is : 1
Value of *++ptr : 2
2.后递增指针:后递增运算符将操作数递增1,但是表达式的值将是操作数的值,而不是操作数的递增值。假设ptr是一个指针,则后递增指针表示为ptr ++。
让我们通过一个例子来理解这一点:
#include
using namespace std;
int main()
{
int a[5]={1,2,3,4,5};
int *ptr;
ptr=&a[0];
cout<<"Value of *ptr is : "<<*ptr<<"\n";
cout<<"Value of *ptr++ : "<<*ptr++;
return 0;
}
输出:
Value of *ptr is : 1
Value of *ptr++ : 1
Std是C++中使用的默认名称空间标准。
发现C++是为了应对C的缺点。
Delete用于释放一个内存单元,delete []用于释放数组。
STL代表标准模板库。
对象是类的实例。一个类为对象提供了一个蓝图。因此,您可以从类创建对象。类的对象的声明与我们声明基本类型的变量的声明相同。
访问说明符用于定义如何在类外部访问函数和变量。
有三种类型的访问说明符:
OOP是一种提供许多概念的方法或范式。面向对象编程的基本概念如下:
类和对象:类用于指定数据的结构。它们定义数据类型。您可以从一个类中创建任意数量的对象。对象是类的实例。
封装:封装是一种将数据和关联的操作绑定在一起,从而将数据隐藏在外部世界中的机制。封装也称为数据隐藏。在C++中,它是使用访问说明符(即公共,私有和受保护的)来实现的。
抽象:抽象用于隐藏内部实现,并仅向外部世界显示必要的细节。数据抽象是使用C++中的接口和抽象类实现的。
有些人对封装和抽象感到困惑,但是他们都是不同的。
继承:继承用于将一个类的属性继承到另一个类。它可以帮助您用另一类来定义一个类。
有两种方法:
朋友函数充当班级的朋友。它可以访问该类的私有成员和受保护成员。朋友函数不是该类的成员,但是必须在类定义中列出。非成员函数无法访问该类的私有数据。有时,非成员函数必须访问数据。朋友函数是非成员函数,并且具有访问类的私有数据的能力。
为了使外部函数对类友好,我们需要将函数声明为类的朋友,如下所示:
class sample
{
// data members;
public:
friend void abc(void);
};
以下是朋友函数的特征:
让我们通过一个例子来理解这一点:
#include
using namespace std;
class Addition
{
int a=5;
int b=6;
public:
friend int add(Addition a1)
{
return(a1.a+a1.b);
}
};
int main()
{
int result;
Addition a1;
result=add(a1);
cout<
输出:
11
虚函数规则:
您可以通过三种方式回答此问题:
析构函数用于删除对象分配的任何额外资源。对象超出范围后,将自动调用析构函数。
破坏者规则:
这是一种算术错误。当算术运算的结果大于系统提供的实际空间时,就会发生这种情况。
1.运算符重载:运算符重载是一种编译时多态性,其中标准运算符被重载以为其提供用户定义的定义。例如,’+’运算符被重载以对int,float等数据类型执行加法运算。
运算符重载可以通过以下功能实现:
运算符重载的语法:
Return_type classname :: Operator Operator_symbol(argument_list)
{
// body_statements;
}
2.函数重载:函数重载也是一种编译时多态性,可以定义具有相同名称的一系列函数。该函数将根据函数调用中的参数列表执行不同的操作。要调用的函数取决于参数数量和参数列表中参数的类型。
如果您将一个类继承到派生类中,并在派生类中再次为基类的函数之一提供定义,则此函数称为覆盖函数,该机制称为函数覆盖。
使用虚拟继承,即使对象在层次结构中出现多个,您也可以仅为每个对象创建一个副本。
构造函数是一种初始化对象的特殊方法。其名称必须与类名称相同。
“删除”运算符用于释放“新”运算符创建的动态内存。
该指针保存当前对象的地址。
范围解析运算符(::)用于在类外部定义成员函数。
Delete []用于释放使用new []分配的已分配内存的数组,而delete用于释放使用new分配的一块内存。
纯虚函数是不包含任何定义的虚函数。正常函数之前带有关键字virtual。纯虚函数以0结尾。
纯虚函数的语法:
virtual void abc()=0; //pure virtual function.
让我们通过一个例子来理解这一点:
#include
using namespace std;
class Base
{
public:
virtual void show()=0;
};
class Derived:public Base
{
public:
void show()
{
cout<<"javaTpoint";
}
};
int main()
{
Base* b;
Derived d;
b=&d;
b->show();
return 0;
}
输出:
javaTpoint
Structures | class |
---|---|
A structure is a user-defined data type which contains variables of dissimilar data types. | The class is a user-defined data type which contains member variables and member functions. |
The variables of a structure are stored in the stack memory. | The variables of a class are stored in the heap memory. |
We cannot initialize the variables directly. | We can initialize the member variables directly. |
If access specifier is not specified, then by default the access specifier of the variable is “public”. | If access specifier is not specified, then by default the access specifier of a variable is “private”. |
The instance of a structure is a “structure variable”. | |
Declaration of a structure:
struct structure_name { // body of structure; } ; |
Declaration of class:
class class_name { // body of class; } |
A structure is declared by using a struct keyword. | The class is declared by using a class keyword. |
The structure does not support the inheritance. | The class supports the concept of inheritance. |
The type of a structure is a value type. | The type of a class is a reference type. |
类模板用于创建一系列类和函数。例如,我们可以创建一个数组类的模板,这将使我们能够创建各种类型的数组,例如int,float,char等。类似地,我们可以为一个函数创建一个模板,假设我们有一个函数add (),然后我们可以创建add()的多个版本。
类模板的语法:
template
class classname
{
// body of class;
};
模板类对象的语法:
classname objectname(arglist);
函数重载:定义函数重载是因为我们可以拥有同一函数的多个版本。函数的版本将具有不同的签名,这意味着它们具有不同的参数集。
运算符重载:定义运算符重载是因为可以重新定义标准运算符,以便在应用于类的实例时具有不同的含义。
基类使用C++中的虚拟析构函数,以便也可以销毁派生的类对象。通过使用〜波浪号运算符,然后在构造函数之前使用virtual关键字,可以声明虚拟析构函数。
注意:构造函数不能是虚拟的,但是析构函数可以是虚拟的。
让我们通过一个例子来理解
#include
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base constructor is called"<<"\n";
}
~Base()
{
cout<<"Base class object is destroyed"<<"\n";
}
};
class Derived:public Base
{
public:
Derived()
{
cout<<"Derived class constructor is called"<<"\n";
}
~Derived()
{
cout<<"Derived class object is destroyed"<<"\n";
}
};
int main()
{
Base* b= new Derived;
delete b;
return 0;
}
输出:
Base constructor is called
Derived class constructor is called
Base class object is destroyed
在上面的示例中,delete b将仅调用基类析构函数,这是因为派生类析构函数保持不变。这导致内存泄漏。
#include
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base constructor is called"<<"\n";
}
virtual ~Base()
{
cout<<"Base class object is destroyed"<<"\n";
}
};
class Derived:public Base
{
public:
Derived()
{
cout<<"Derived class constructor is called"<<"\n";
}
~Derived()
{
cout<<"Derived class object is destroyed"<<"\n";
}
};
int main()
{
Base* b= new Derived;
delete b;
return 0;
}
输出:
Base constructor is called
Derived class constructor is called
Derived class object is destroyed
Base class object is destroyed
当我们使用虚拟析构函数时,则首先调用派生类析构函数,然后再调用基类析构函数。