某日二師兄參加XXX科技公司的C++工程師開發崗位第9面:
面試官:C++中,設計一個類要注意哪些東西?
二師兄:設計一個類主要考慮以下幾個方面:1.面向物件的封裝、繼承及多型,2.
big three或者big five,3.運算子和函式多載、靜態成員、友元、例外處理等相關問題,面試官:請介紹一下面向物件的三個特性,
二師兄:封裝是將類的函式和資料封裝起來,外部不能直接訪問類的資料,而是需要通過方法訪問資料,繼承是指一個類可以繼承另一個類的屬性和方法,多型是指一個物件可以表現出多種形態,
面試官:請問多型是如何實作的?
二師兄:多型的是通過父類的指標或參考指向子類的物件實作的,在物件中維護一個虛指標(
vtptr),這個指標指向一個虛表(vtable),當用戶通過父類物件訪問子類的方法時,通過查詢虛表中對應的方法的地址,并跳轉到此地址執行間接訪問物件的方法,所以多型是有一點點運行時開銷的,面試官:你剛才所說的
big three和big 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;
}
好了,今日份面試到這里就結束了,小伙伴們,對于今天二師兄的面試,能打幾分呢?如果是你,以上的問題都能回答的上來嗎?
關注我,帶你21天“精通”C++!(狗頭)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/554678.html
標籤:其他
上一篇:python 爬蟲某東網商品資訊 | 沒想到銷量最高的是
下一篇:返回列表
