首页 > 编程语言 >C++面试八股文:C++中,设计一个类要注意哪些东西?

C++面试八股文:C++中,设计一个类要注意哪些东西?

时间:2023-06-14 22:33:41浏览次数:46  
标签:面试官 const 成员 C++ 类要 八股文 移动 师兄

某日二师兄参加XXX科技公司的C++工程师开发岗位第9面:

面试官:C++中,设计一个类要注意哪些东西?

二师兄:设计一个类主要考虑以下几个方面:1.面向对象的封装、继承及多态。2.big three或者big five。3.运算符和函数重载、静态成员、友元、异常处理等相关问题。

面试官:请介绍一下面向对象的三个特性。

二师兄:封装是将类的函数和数据封装起来,外部不能直接访问类的数据,而是需要通过方法访问数据。继承是指一个类可以继承另一个类的属性和方法。多态是指一个对象可以表现出多种形态。

面试官:请问多态是如何实现的?

二师兄:多态的是通过父类的指针或引用指向子类的对象实现的。在对象中维护一个虚指针(vtptr),这个指针指向一个虚表(vtable),当用户通过父类对象访问子类的方法时,通过查询虚表中对应的方法的地址,并跳转到此地址执行间接访问对象的方法。所以多态是有一点点运行时开销的。

面试官:你刚才所说的big threebig five是什么?

二师兄:(嘿嘿,被装到了)类的big three分别是拷贝构造函数(copy constructor)、拷贝赋值运算符(copy assignment)和析构函数。而类的big five则多了两个,分别是移动构造函数(move constructor)和移动赋值运算符(move assignment)。后面两个是C++11之后引入的。

面试官:好的。那你知道为什么要引入移动构造和移动赋值吗?

二师兄:主要是为了效率。移动构造和移动赋值不需要把所有的数据重新拷贝一遍,而是霸占了被移动对象的数据的所有权。代价是被移动对象在被移动后不能使用。

面试官:嗯。那你知道为什么移动构造和移动赋值都要加上noexcept关键字吗?

二师兄:额。。。好像不让抛异常?

面试官:你知道类的静态成员变量需要注意哪些问题吗?

二师兄:要注意哪些问题?额。。。

面试官:在成员方法后加const是为什么?

二师兄:主要是为了约束这个成员方法不更改对象的任何数据。

面试官:还有其他的原因吗?

二师兄:好像没有了吧。。。

面试官:类的成员方法可以通过const符号重载吗?

二师兄:这个,,应该可以吧。。

面试官:你知道什么是类的成员方法的引用限定符吗?

二师兄:没有听说过耶。。。

面试官:好的,回去等通知吧。

让我们来看一看今日二师兄的表现吧,

为什么移动构造和移动赋值都要加上noexcept关键字?

因为在使用移动语义时,通常会将资源的所有权从一个对象转移到另一个对象,而不是复制资源。如果抛出异常,那么在转移资源的过程中可能会出现问题,导致资源泄漏或其他不可预测的行为。

另外,加上 noexcept 关键字还可以提高代码的性能,因为编译器可以在不必要的情况下进行优化。

类的静态成员变量需要注意哪些问题?

静态成员变量的初始化顺序是不确定的。如果一个静态成员变量依赖于另一个静态成员变量的值,要确保第二个静态化成员先被初始化,否则程序可能会出现未定义的行为。

静态成员变量的值可以被多个实例同时修改,因此在多线程访问静态成员时要注意数据竞争问题。静态变量的生命周期与程序的生命周期相同,因此它们可能会占用大量的内存。

在成员方法后加const是为什么?

一是可以约束此方法不会更改对象的任何数据。二是cosnt对象也可以访问此成员方法。

#include <iostream>
struct Foo
{
    void f1(){std::cout <<"f1" << std::endl;}
    void f2() const{std::cout <<"f2" << std::endl;}
};
int main(int argc, char const *argv[])
{
    Foo foo;
    foo.f1();
    foo.f2();
    const Foo& foo2 = foo;
    foo2.f1();  //这里无法通过编译,因为const对象无法访问非const 方法
    foo2.f2();  //这里可以通过编译
}

类的成员方法可以通过const符号重载吗?

这是一个很好的问题,估计很多人没有思考过。先说答案,底层const可以,而顶层const不可以。

#include <iostream>
struct Foo{};
struct Goo
{
    void f1(Foo& f){std::cout <<"non const function" << std::endl;}
    void f1(const Foo& f){std::cout <<"const function" << std::endl;}
};
int main(int argc, char const *argv[])
{
    Foo foo;
    Goo goo;
    goo.f1(foo);    //无法通过编译,error: ‘void Goo::f1(Foo)’ cannot be overloaded with ‘void Goo::f1(Foo)’
    return 0;
}

当我们把顶层const改为底层const

#include <iostream>
struct Foo{};
struct Goo
{
    void f1(Foo& f){std::cout <<"non const function" << std::endl;}
    void f1(const Foo& f){std::cout <<"const function" << std::endl;}
};
int main(int argc, char const *argv[])
{
    Foo non_const_foo;
    const Foo const_foo;
    Goo goo;
    goo.f1(non_const_foo);    //可以通过编译	non const function
    goo.f1(const_foo);    //可以通过编译 const function
    return 0;
}

那么我们能否通过在函数括号后加上const来重载函数呢?

#include <iostream>
struct Goo
{
    void f1() {std::cout <<"non const function" << std::endl;}
    void f1() const{std::cout <<"const function" << std::endl;}
};
int main(int argc, char const *argv[])
{
    Goo non_const_goo;
    const Goo const_goo;
    non_const_goo.f1();   
    const_goo.f1();   
    return 0;
}

答案是肯定的,因为const_goo.f1() 可以等同于f1(const Goo* goo),也是底层const

最后一个问题虽然简单,但我相信至少有80%的C++程序员不知道是什么,

什么是类的成员方法的引用限定符吗?

类的成员方法的引用限定符是 C++11 中引入的一种新特性,用于指定成员方法的参数是左值引用还是右值引用。

#include <iostream>
struct Foo
{
    void f1() & {std::cout << "only left reference can call this function" << std::endl;}
    void f1() && {std::cout << "only right reference can call this function" << std::endl;}
};
int main(int argc, char const *argv[])
{
    Foo foo;
    foo.f1();       //left reference
    Foo().f1();     //right reference
    return 0;
}

标签:面试官,const,成员,C++,类要,八股文,移动,师兄
From: https://www.cnblogs.com/bujidao1128/p/17481540.html

相关文章

  • 《C++》对象的初始化和清理
    不设计构造和析构函数 编译器会提供空语句的构造和析构初始化--构造函数无返回类型函数名与类名相同构造函数可以有参数可以发生重载创建对象的时候构造函数会自动调用且只调用一次classPerson{public: Person() { cout<<"无参构造函数调用"<<endl; }Person(inta......
  • C++ const_cast用法
    原文C++const_cast用法const_cast是一种C++运算符,主要是用来去除复合类型中const和volatile属性(没有真正去除)。变量本身的const属性是不能去除的,要想修改变量的值,一般是去除指针(或引用)的const属性,再进行间接修改。用法:const_cast<type>(expression)通过const_cast运算符,也只......
  • [C++/PTA] 有序数组(类模板)
    题目要求实现一个类模板,它可以接受一组数据,能对数据排序,也能输出数组的内容。每行输入的第一个数字为0,1,2或3:为0时表示输入结束;为1时表示将输入整数,为2时表示将输入有一位小数的浮点数,为3时表示输入字符。如果第一个数字非0,则接下来将输入一个正整数,表示即将输入的数据的数量......
  • [C++/PTA] 2017Final 圆周率山
    题目要求为了参加学校的社团风采展,怡山小学数学组的同学们决定画一座圆周率山,以宣传圆周率。已知圆周率为:3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253......
  • [C++/PTA] 类的定义和使用
    题目要求定义一个日期类Date,内有数据成员年、月、日,另有成员函数:构造函数用于初始化数据成员,输出,闰年的判断。编写主函数:创建日期对象,计算并输出该日是该年的第几天。输入:每组测试数据仅包含一个测试用例,每个测试用例占一行包括三个数,分别表示年、月、日。输出:该日是该年的......
  • [C++/PTA] 立方体类的实现
    题目要求立方体类Box的实现,完成计算体积、计算表面积、输出结果等功能。其中给定的主函数为:intmain(){floatab;cin>>ab;Boxobj;obj.seta(ab);obj.getvolume();obj.getarea();obj.disp();return0;}输入格式:立方体的边......
  • [C++/PTA] 汽车收费
    题目要求现在要开发一个系统,管理对多种汽车的收费工作。给出下面的一个基类框架classVehicle{protected:stringNO;//编号public:virtualvoiddisplay()=0;//输出应收费用}以Vehicle为基类,构建出Car、Truck和Bus三个类。Car的收费公式为:载客数8+重量2Truck的收费......
  • [C++/PTA] 计算时间相减
    题目要求题目描述:定义一个时间类,小时和分钟是其两个私有成员数据。输入一个起始时间和一个结束时间(起始时间早于结束时间),通过运算符重载-(减号),计算这两个时间相隔多少分钟。说明:这两个时间在同一天之内,且采用24小时计时分式,即从00:00-23:59。输入格式:测试输入包含若干测......
  • [C++/PTA] 括号匹配
    题目要求给定仅包含()[]{}六种括号的字符串,请你判断该字符串中,括号的匹配是否是合法的,也就是对应括号的数量、嵌套顺序完全正确。输入格式:第一行一个整数T(T<=10)其后T行每行一个字符串只包含[{()}]六种字符(字符串长度2e5以内)输出格式:对于每个字符串,匹配输出Yes,否则输出No......
  • c++的常量折叠
    一,前言有关C++语言的const常量的考察点:肯定是const常量的内存不是分配在read-only的存储区的,const常量的内存分配区是很普通的栈或者全局区域。也就是说const常量只是编译器在编译的时候做检查,根本不存在什么read-only的区域。所以说C++的const常量和常量字符串是不同的,常量字符......