Giải đáp những câu phỏng vấn C/C++ của John Sonmez


Đây là những câu hỏi rất hay tớ đọc được trong bài viết Tại sao C/C++ không còn là sự lựa chọn cho bạn nữa ? của John Sonmez, do vinacode dịch. Để giải đáp được những câu hỏi này cần có kiến thức khá vững về C/C++ và nó luôn thôi thúc tớ đi tìm câu trả lời, nhưng không phải trả lời theo kiểu search google và chép đáp án vào, mà tớ muốn bản thân tớ ( và các bạn cũng vậy) phải tiếp xúc với kiến thức trong câu hỏi đó đủ nhiều và có một sự mạch lạc trong tư duy khi giải thích lại nó.

Ok, ko dài dòng nữa, đây là danh sách:

1. Có bao nhiêu cách để khởi tạo một kiểu dữ liệu nguyên thủy trong C++ và đó là những cách nào?

Hiện tại mình có thể nêu ra 3 cách:
int var_1; <- Khởi tạo biến var_1 với giá trị mặc định do môi trường quyết định
int var_1(4); <- Khởi tạo biến var_1 với giá trị được truyền vào
int var_1(var_2); <- Khởi tạo biến var_1 với giá trị của var_2 (copy constructor)
Update:
int var_1 = 4; <- implicit cast
int var_1{4}; <- inintializer list

2. Tại sao bạn nên khai báo một hàm hủy là ảo (virtual) ?

Giả sử có class Parent và class Child kế thừa từ Parent. Ta định nghĩa con trỏ:
Parent * p = new Child();
Lúc này để tạo ra Child(), thì Parent() phải được tạo ra trước. Khi chúng ta delete p, thì cả 2 đối tượng này cũng phải được gọi Destructor.
Vậy nếu không khai báo virtual cho hàm Destructor của Parent, thì chỉ Destructor của Parent được gọi, đối tượng Child() vẫn còn đó
3. Nó có nghĩa gì khi nói rằng C++ hỗ trợ overloading (nạp chồng)?
4. Nêu ra một số ví dụ về overloading trong C++?
5. Khái niệm name mangling trong C++ có nghĩa là gì và tại sao nó lại được sử dụng?
6. Một lớp trừu tượng cơ sở (abstract base) có nghĩa là gì?
7. RTTI có nghĩa là gì?
8. Làm thế nào để bạn có thể truy cập một biến mà nó bị “che khuất” bởi một biến khác có cùng tên?

Có thể sử dụng namespace: đưa 2 biến cùng tên đó vào 2 namespace khác nhau, bạn có 2 biến cùng tên var:
namespace ns1 { int var;}
namespace ns2 { int var;}
Cách truy cập:
ns1::var = 6;
ns2::var = 9;

Cũng có thể dùng class và struct nhưng cách đó khá thô thiển vì phải tạo nên thể hiện của class và struct

Update: Trường hợp biến local bị che khuất bởi biến global có cùng tên, có thể sử dụng toán tử truy cập phạm vi :: để gọi biến global

int x;
int func()
{
int x;
x = 3;    // local
::x = 3; // global
}

9. Khái niệm namespace có nghĩa là gì và làm thế nào để sử dụng nó?

Mới gặp ngay ở câu 8 :))
namespace theo như cách dịch thì là “không gian tên”, tớ cũng chẳng biết dịch như thế nào cho đúng, chỉ biết là nó được dùng để phân loại, gom các đối tượng vào thành một nhóm. Cách dùng như sau:
namespace <name> { // declare or define }
Ví dụ: Tớ có một namespace tên nsmath, và trong namespace này tớ sẽ khai báo một biến distance, một hàm Add và một class Point chẳng hạn

namespace nsmath
</span><span class="text_exposed_show">{
float distance;
float Add(float a, float b);
class Point;
}


Bạn có thể chỉ khai báo propotype như thế, và định nghĩa các hàm và class bên ngoài (như class):

float nsmath::Add(float a, float b) { // add a to b }
class nsmath::Point { // construct };


10. Điểm khác nhau giữa một lớp và một cấu trúc (struct) trong C++ là gì, và so sánh với ngôn ngữ C thì như thế nào?

Điểm khác nhau duy nhất giữa class và struct trong C++ đó là, những thuộc tính của class nếu để mặc định thì nó là private, của struct là public.
So sánh với ngôn ngữ C: ?

11. Khái niệm template là gì? Làm thế nào để sử dụng chúng ?
12. Một hàm tạo sao chép (copy constructor) có nghĩa là gì và khi nào thì nó được sử dụng, đặc biệt là khi so sánh với toán tử =
13. Điểm khác nhau giữa một sao chép “shallow” và “deep” là gì?

14. Hằng toán tử (const operator) nghĩa là gì và nó được sử dụng như thế nào?
15. Điểm khác nhau giữa truyền tham chiếu, truyền tham trị, và truyền bởi con trỏ trong C++ là gì?
16. Khi nào thì nên và khi nào thì không nên trả về một giá trị bởi tham chiếu trong C++?
17. Điểm khác nhau giữa một biến tạo ra trên ngăn xếp (stack) và một biến tạo ra trên heap là gì?

Biến trên stack tự giải phóng khi ra khỏi khối lệnh ( block )
Biến trên heap phải dùng free() ( C ) hoặc delete ( C++ ) để giải phóng


18. Làm thế nào để bạn giải phóng bộ nhớ đã cấp phát động cho một mảng?
19. Đa kế thừa là gì? Khi nào thì nó nên được sử dụng?
20. Một hàm ảo thuần túy (pure virtual) là gì?
21. Từ khóa mutable có ý nghĩa gì?
22. Từ khóa volatile có ý nghĩa gì?
23. Khái niệm STL có nghĩa là gì?
24. Khái niệm Vector có nghĩa là gì?

Vector là một cấu trúc dữ liệu được xây dựng sẵn trong C++

25. Cái gì được chứa strong phần header <algorithms>?
26. Điểm khác nhau giữa ‪#‎include‬ <iostream.h> và #include <iostream> là gì?

iostream.h là thư viện cũ, được thay thế bởi iostream từ C++ 98.
iostream.h được khai báo toàn cục, còn iostream được khai báo cục bộ
Thêm cái nữa đó là nếu #include <iostream.h> thì không cần phải thông báo sử dụng namespace std, nhưng #include <iostream> thì cần

27. Điểm khác nhau giữa “++i” and “i++” là gì?

++i: cộng i lên 1 trước rồi thực hiện phép toán
i++: thực hiện phép toán trước rồi cộng i lên 1
28. Ước lượng short circuit có nghĩa là gì? Nó được sử dụng như thế nào? Tại sao việc sử dụng nó có thể gây nguy hiểm?
29. Toán tử ‘,’ có ý nghĩa gì?
30. Toán tử tam nguyên có nghĩa là gì? Cách sử dụng nó như thế nào?
31. Hàm hằng thành viên (const member) có nghĩa là gì và nó được sử dụng như thế nào?
32. Làm thế nào để sử dụng try/catch trong C++?
33. Tại sao bạn đừng bao giờ ném ra một ngoại lệ trong một hàm hủy?
34. Từ khóa explicit có ý nghĩa gì?

Từ khoá explicit đặt trước Constructor một tham số của một class, thì đối tượng của class này không thể tạo ra bằng implicit cast

class A {
public:
explicit A ( int data ) { // ... }
}
int main() {
A a ( 3 );    // RIGHT
A a = 3;     // WRONG

35. Đâu là cách đúng để thực thi một ép kiểu trong C++?
36. Khái niệm inline có nghĩa là gì?

Advertisements

9 thoughts on “Giải đáp những câu phỏng vấn C/C++ của John Sonmez

  1. Câu 8: Bổ sung tí, nếu biến bị che khuất là biến cục bộ thì chỉ cần dùng ::

    Like

      • Nếu là biến cục bộ, ví dụ:
        int x=10;
        int add()
        {
        int x= 8;
        return x+ ::x // ::x để gọi biến cục bộ bị che khuất;
        }// return 18;

        Nếu là biến địa phương, thì cách của bạn là cách duy nhất, nhưng chỉ cần tạo namespace cho biến bị che khuất thôi.
        Thật ra ở trường hợp biến cục bộ; cũng là một kỹ thuật dùng namespace: Mọi biến cục bộ tạo ra sẽ nằm trong Global Namespace – một namespace được using tự động; và :: là cách để gọi Global Namespace đó.

        Che khuất là hiện tượng xảy ra khi một biến X trong phạm vi sử dụng (scope) của nó xuất hiện một biến khác cùng tên, biến X sẽ tự động giấu mình đi trong thời gian hoạt động(duration) của biến cùng tên, khi duration của biến cùng tên kết thúc, biến X sẽ hoạt động trở lại..
        Ví dụ:
        void vidu()
        {
        int x=8;
        for(int y=0;y<5;y++)
        if(x==8)
        {
        int x=6;// từ đây biến x(8) bị che khuất
        cout<<x<<" ";
        } // duration biến x(6) kết thúc, biến x(8) lại được kích hoạt

        }
        Kết quả: 6 6 6 6 6

        Một chút chém gió góp vui :v

        Liked by 1 person

      • Ồ cảm ơn bạn đã chia sẻ, rất hay ! Giúp mình biết được một kiến thức mới. Mình xin phép trích dẫn câu trả lời của bạn vào phần giải đáp của mình được không ? 🙂

        Like

      • À, mình cũng góp ý với bạn là hình như bạn nhầm giữa biến cục bộ / địa phương / toàn cục thì phải.
        Theo mình thì: biến cục bộ = biến địa phương ( local variable ), và 2 biến này # biến toàn cục ( global variable ).
        Nên trong comment của bạn mình nghĩ sửa “biến cục bộ” thay bằng “biến toàn cục” thì mới đúng

        Like

  2. Câu 8: nếu là biến ở các namespace độc lập nhau thì ko thể gọi là “che khuất” được. Có lẽ người hỏi muốn nói đến các trường hợp sau:

    int x=10; //global variable
    void foo() {
    int x = 8; //local variable
    printf(“%d”,x);
    }

    void foo() {
    int x = 8; //local variable
    if(true) {
    int x = 6; //variable in a sub-scope
    printf(“%d”,x);
    }
    }

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s