close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

50 câu hỏi, trả lời phỏng vấn C và C++ – Phần 2

Nội dung

C++ là xương sống của nhiều ứng dụng doanh nghiệp do sự phổ biến của nó. Cơ hội việc làm ở C++ là rất lớn. Do đó, dưới đây là một số câu hỏi phỏng vấn về C++ mà bạn có thể xem qua sẽ giúp bạn chuẩn bị cho cuộc phỏng vấn C++.

Xem lại 50 câu hỏi, trả lời phỏng vấn C và C++ – Phần 1

Q26. Kết quả của chương trình này là gì?

#include <stdio.h>
#include<iostream>
using namespace std;
int main()
{
    int a = 5, b = 10, c = 15;
    int arr[3] = {&a, &b, &c};
    cout << *arr[*arr[1] – 8];
    return 0;
}

Biên dịch chương trình lỗi. Lỗi không thể chuyển đổi ‘int*’ thành ‘int’ sẽ được in ra. Đó là do &a, &b và &c đại diện cho int* trong khi mảng được xác định là kiểu int.

Q27. Kết quả của chương trình này là gì?

#include <iostream>
using namespace std;
int main()
{
    int arr[] = {4, 5, 6, 7};
    int *p = (arr + 1);
    cout << *p;
    return 0;
}

Kết quả là 5. Chúng ta đang cho con trỏ trỏ đến giá trị tiếp theo và in ra nó.

Q28. Kết quả của chương trình này là gì?

#include <iostream>
using namespace std;
int main()
{
    int arr[] = {4, 5, 6, 7};
    int *p = (arr + 1);
    cout << *arr + 9;
    return 0;
}

Kết quả là 13 vì chúng ta đang cộng thêm 9 vào giá trị đầu tiên trong mảng.

Q29. Các thành phần của hằng ký tự (literals constant) là gì?

  1. Các số nguyên.
  2. Các số chấm động.
  3. Các chuỗi và giá trị boollean.
  4. Các đáp án trên.

Kết quả: 4

Q30. Hằng được khai báo như thế nào?

Sử dụng từ khoá const để khai báo hằng với kiểu cụ thể hoặc sử dụng #define.

Q31. Thực hiện một hàm F có kiểu trả về là void và nhận các con trỏ đến hai mảng số nguyên (A và B) và kích thước N làm tham số. Sau đó, nó tính tích B trong đó B[i] là tích của tất cả A[j] trong đó j! = i.

void F(int* A, int* B, int N)
{
    int m = 1;
    for(int i = 0; i < N; ++i) {
        m *= A[i];
    }
    for (int i = 0; i < N; ++i) {
        B[i] = m / A[i];
    }
}

Q32. Khi nào nên sử dụng thừa kế virtual?

Mặc dù lý tưởng nhất là tránh hoàn toàn thừa kế ảo (chúng ta nên biết lớp của mình sẽ được sử dụng như thế nào) nhưng việc hiểu rõ về cách hoạt động của kế thừa ảo vẫn là điều quan trọng:

Vì vậy, khi ta có một lớp (lớp A) kế thừa từ 2 lớp cha (B và C), cả hai lớp này đều chia sẻ một lớp cha (lớp D), như được minh họa bên dưới:

#include <iostream>
class D {
public:
    void foo() {
        std::cout << “Foooooo” << std::endl;
    }
};
class C: public D {
};
class B: public D {
};
class A: public B, public C {
};
int main(int argc, const char * argv[]) {
    A a;
    a.foo();
}

Q33. Có sự khác biệt gì giữa struct và class không?

Sự khác biệt duy nhất giữa class và struct là các công cụ sửa đổi quyền truy cập. Các thành viên struct được công khai theo mặc định; các thành viên trong class là riêng tư. Cách tốt là sử dụng các class khi bạn cần một đối tượng có các phương thức và struct khi bạn có một đối tượng dữ liệu đơn giản.

Q34. Cho biết kết quả của chương trình sau?

#include <iostream>
int main(int argc, const char * argv[]) 
{ 
    int a[] = {1, 2, 3, 4, 5, 6};
    std::cout << (1 + 3)[a] – a[0] + (a + 1)[2];
}

Kết quả chương trình trên là 8, vì (1+3)[a] thì giống như a[1+3] = 5, a[0] = 1 và (a + 1)[2] thì giống như a[3] = 4.

Câu hỏi này dùng để kiểm tra kiến ​​thức số học của con trỏ và điều kỳ diệu đằng sau dấu ngoặc vuông với con trỏ.

Mặc dù một số người có thể tranh luận rằng đây không phải là một câu hỏi có giá trị vì nó dường như chỉ kiểm tra khả năng đọc các cấu trúc C, nhưng điều quan trọng là ứng viên phải có khả năng vượt qua nó về mặt tinh thần; đó không phải là câu trả lời mà họ dự kiến sẽ biết ngay từ đầu, mà là câu trả lời nơi họ nói về kết luận mà họ đạt được và cách thức thực hiện nó.

Q35. Giải thích các từ khóa volatile và mutable.

Từ khóa volatile thông báo cho trình biên dịch rằng một biến có thể thay đổi mà trình biên dịch không biết. Các biến được khai báo là volatile sẽ không được trình biên dịch lưu vào bộ nhớ đệm cache và do đó sẽ luôn được đọc từ ram.

Từ khóa mutable có thể được sử dụng cho các biến thành viên của lớp. Các biến mutable được phép thay đổi từ bên trong các hàm thành viên const của lớp.

Q36. Vòng lặp sau sẽ lặp bao nhiêu lần?

unsigned char half_limit = 150;
for (unsigned char i = 0; i < 2 * half_limit; ++i)
{
    // do something;
}

Nếu bạn nói 300, bạn sẽ đúng nếu nó được khai báo là một int. Tuy nhiên, vì nó được khai báo là unsigned char, câu trả lời chính xác là mã này sẽ dẫn đến một vòng lặp vô tận.

Biểu thức 2 * half_limit sẽ được thăng cấp thành int (dựa trên quy tắc chuyển đổi C++) và sẽ có giá trị là 300. Tuy nhiên, vì nó là một unsigned char, nên nó được đánh dấu lại bằng một giá trị 8 bit, sau khi đạt đến 255, sẽ tràn (vì vậy nó sẽ trở về 0) và vòng lặp do đó sẽ tiếp diễn mãi mãi.

Q37. Bạn có được phép có một hàm thành viên const tĩnh không? Giải thích câu trả lời của bạn.

Hàm thành viên const là một hàm không được phép sửa đổi các thành viên của đối tượng mà nó được gọi. Hàm thành viên tĩnh là một hàm không thể được gọi cho một đối tượng cụ thể. Do đó, sửa đổi const cho một hàm thành viên tĩnh là vô nghĩa, bởi vì không có đối tượng nào được liên kết với lời gọi.

Một lời giải thích chi tiết hơn về lý do này đến từ ngôn ngữ lập trình C. Trong C, không có các lớp và các hàm thành viên, vì vậy tất cả các hàm đều là toàn cục. Một lời gọi hàm thành viên được dịch thành một lời gọi hàm toàn cục.

Hãy xem xét một hàm thành viên như void foo(int i);. Một lời gọi hàm obj.foo(10); sẽ được biên dịch thành foo(&obj, 10);. Điều này có nghĩa là hàm thành viên foo có đối số đầu tiên bị ẩn kiểu T*, void foo(T* const this, int i);, Nếu một hàm thành viên là const, thì đây là kiểu const T* const, void foo(const T* const this, int i);. Hàm thành viên tĩnh không có đối số ẩn như vậy, vì vậy không có con trỏ this là const hay không.

Q38. Lớp lưu trữ là gì?

Một lớp xác định vòng đời và phạm vi của các biến và hàm của nó được gọi là lớp lưu trữ.

Trong C++, các lớp lưu trữ sau được hỗ trợ: auto, static, register, extern và mutable.

Tuy nhiên, lưu ý rằng từ khóa register không được chấp nhận trong C++11.

Trong C++17, nó đã bị loại bỏ và dành để sử dụng trong tương lai.

Q39. Một hàm C được gọi trong chương trình C++ như thế nào?

Sử dụng khai báo extern C.

//C code
void func(int i)
{
    //code
}
void print(int i)
{
    //code
}
//C++ code
extern “C”{
    void func(int i);
    void print(int i);
}
void myfunc(int i)
{
    func(i);
    print(i);
}

Q40. Vòng lặp lồng nhau là gì

Vòng lặp lồng nhau là một vòng lặp chạy trong một vòng lặp khác. Nói một cách khác, bạn có một vòng lặp bên trong nằm trong một vòng lặp bên ngoài.

Trong trường hợp này, vòng lặp bên trong thực hiện một số lần như được chỉ định bởi vòng lặp bên ngoài.

Đối với mỗi lượt trên vòng ngoài, vòng trong được thực hiện đầu tiên.

Q41. Danh sách liên kết là gì?

Một danh sách được liên kết bao gồm các nút được kết nối với một danh sách khác.

Trong lập trình C, danh sách liên kết được tạo bằng cách sử dụng con trỏ. Sử dụng danh sách được liên kết là một cách hiệu quả để sử dụng bộ nhớ để lưu trữ.

Q42. Từ dành riêng là gì?

Các từ dành riêng là những từ nằm trong thư viện ngôn ngữ C chuẩn.

Điều này có nghĩa là các từ dành riêng có ý nghĩa đặc biệt và do đó không thể được sử dụng cho mục đích khác với mục đích ban đầu của nó.

Ví dụ về các từ dành riêng là int, void và return.

Q43. Sự khác biệt giữa ghi đè và nạp chồng phương thức là gì?

Nạp chồng một phương thức (hoặc hàm) trong C ++ là khả năng các hàm có cùng tên được xác định miễn là các phương thức này có các chữ ký khác nhau (tập tham số khác nhau).
Ghi đè phương thức là khả năng của lớp kế thừa viết lại phương thức ảo của lớp cơ sở.

Q44. Cho biết kết quả của chương trình sau?

#include <iostream>
using namespace std;
#define PI 3.14159
int main ()
{
    float r = 2;
    float circle;
    circle = 2 * PI * r;
    cout << circle;
    return 0;
}

Kết quả: 12.5664

Q45. Liên kết sớm (early binding) có nghĩa là gì?

Liên kết sớm đề cập đến các sự kiện xảy ra tại thời điểm biên dịch.

Liên kết sớm xảy ra khi tất cả thông tin cần thiết để gọi một hàm được biết đến tại thời điểm biên dịch.

Ví dụ về liên kết sớm bao gồm các lệnh gọi hàm bình thường, lệnh gọi hàm và toán tử nạp chồng.

Ưu điểm của việc liên kết sớm là hiệu quả.

Q46. Phát biểu nào sau đây không đúng về chỉ thị tiền xử lý?

  1. Đây là những dòng được đọc và xử lý bởi bộ tiền xử lý
  2. Chúng không tự sinh ra bất kỳ mã nào
  3. Chúng phải được viết trên dòng riêng của chúng
  4. Chúng kết thúc bằng dấu chấm phẩy

Đáp án đúng là 4. Các chỉ thị tiền xử lý không cần ký tự kết thúc lệnh.

Q47. Phát biểu nào sau đây là đúng với câu lệnh const int a = 100;?

  1. Khai báo một biến a với 100 là giá trị ban đầu của nó
  2. Khai báo một cấu trúc a với 100 là giá trị ban đầu của nó
  3. Khai báo một hằng số a có giá trị là 100
  4. Tạo một biến kiểu số nguyên với một mã định danh và 100 là giá trị

Đáp án đúng là 3.

Q48. Mục đích chính của nạp chồng toán tử là gì?

Mục đích chính của việc nạp chồng toán tử là để giảm thiểu khả năng xảy ra lỗi trong một lớp đang sử dụng các toán tử nạp chồng.

Nó cũng giúp xác định lại các chức năng của các toán tử để cải thiện hiệu suất của chúng.

Toán tử nạp chồng cũng làm cho chương trình rõ ràng hơn, dễ đọc và dễ hiểu hơn bằng cách sử dụng các toán tử phổ biến, chẳng hạn như +, =, và [].

Q49. Sự khác biệt giữa x và ‘x’ là gì?

Trong mã C++, các tên có dấu nháy như ‘x’ đại diện cho một ký tự hoặc chuỗi (trong trường hợp tập hợp các ký tự) trong khi không có dấu nháy, đại diện cho một nhận dạng (một biến).

Q50. Sự khác biệt giữa C++ và Java là gì?

C++ có con trỏ Java thì không.
Java là nền tảng độc lập vì nó hoạt động trên bất kỳ loại hệ điều hành nào.
Java có bộ sưu tập rác C++ thì không.


Đã đăng vào

trong

,

bởi

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *