C++中设计一个类时的注意事项分享

 更新时间:2023年06月09日 09:03:34   作者:二进制架构  
这篇文章主要来和大家分享一下C++中,设计一个类要注意哪些东西,这往往也是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;
}

好了,今日份面试到这里就结束了,小伙伴们,对于今天二师兄的面试,能打几分呢?如果是你,以上的问题都能回答的上来吗?

到此这篇关于C++中设计一个类时的注意事项分享的文章就介绍到这了,更多相关C++设计类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言代码实现简易三子棋游戏

    C语言代码实现简易三子棋游戏

    这篇文章主要为大家详细介绍了C语言代码实现简易三子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • QT6安装图文教程(兼容QT5、QT4)

    QT6安装图文教程(兼容QT5、QT4)

    本文主要介绍了QT6安装图文教程(兼容QT5、QT4),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • C程序结构的入门

    C程序结构的入门

    在我们学习 C 语言的基本构建块之前,让我们先来看看一个最小的 C 程序结构,在接下来的章节中可以以此作为参考
    2021-06-06
  • 深入解析C++中的mutable关键字

    深入解析C++中的mutable关键字

    在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中
    2013-10-10
  • C语言经典顺序表真题演练讲解

    C语言经典顺序表真题演练讲解

    程序中经常需要将一组数据元素作为整体管理和使用,需要创建这种元素组,用变量记录它们,传进传出函数等。一组数据中包含的元素个数可能发生变化,顺序表则是将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示
    2022-04-04
  • Matlab实现绘制玫瑰线的示例代码

    Matlab实现绘制玫瑰线的示例代码

    这篇文章主要为大家介绍了如何利用Matlab绘制3好看的玫瑰线,文中的示例代码讲解详细,对我们学习Matlab有一定帮助,感兴趣的小伙伴可以动手试一试
    2022-08-08
  • C++中的ilst使用以及模拟实现

    C++中的ilst使用以及模拟实现

    list是一个类模板,加<类型>实例化才是具体的类,可以在任意位置进行插入和删除的序列式容器,本文将通过代码示例给大家介绍一下C++中的ilst使用以及模拟实现,需要的朋友可以参考下
    2023-08-08
  • C++中内存池的简单原理及实现详解

    C++中内存池的简单原理及实现详解

    内存池的思想是,在真正使用内存之前,预先申请分配一定数量、大小预设的内存块留作备用。本文主要来和大家聊聊内存池的简单原理及实现,希望对大家有所帮助
    2023-03-03
  • C++中静态成员函数与静态成员变量(static )

    C++中静态成员函数与静态成员变量(static )

    这篇文章主要介绍了C++中静态成员函数与静态成员变量(static )的相关资料,需要的朋友可以参考下
    2017-06-06
  • 浅谈Qt实现HTTP的Get/Post请求

    浅谈Qt实现HTTP的Get/Post请求

    本文主要介绍了浅谈Qt实现HTTP的Get/Post请求,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05

最新评论