enum, struct, class

enum, struct, class và namespace dùng để gom nhóm các hằng số, hàm, hoặc logic liên quan.

So sánh nhanh

Cách dùngMục đích gom nhómKiểm tra kiểuPhạm vi tênMở rộng logicDễ dùng bitmask
enumGom nhóm hằng số nguyênKhôngKhôngKhông
Có
enum classGom nhóm hằng số nguyênCóCóKhôngCần ép kiểu
structGom nhóm hằng số + hàmKhôngCóCó
Có
classGom nhóm hằng số + hàmKhôngCóCó (kiểm soát access)
Có
namespaceGom nhóm tên (hằng số, hàm, class)KhôngCóCó
Có

“enum” vs “enum class”

// "enum" không cần dùng "::"
#include <iostream>

enum Permission
{
    READ  = 1,
    WRITE = 2,
    EXEC  = 4
};

int main() {
    int userPerm = READ | EXEC;
    if (userPerm & EXEC) {
        std::cout << "Có quyền thực thi\n";
    }
}
// "enum class" an toàn hơn, nhưng cần static_cast<int> khi dùng bitmask.
#include <iostream>

enum class Permission
{
    READ  = 1,
    WRITE = 2,
    EXEC  = 4
};

int main() {
    int userPerm = static_cast<int>(Permission::READ) | static_cast<int>(Permission::EXEC);
    if (userPerm & static_cast<int>(Permission::READ)) {
        std::cout << "Có quyền đọc\n";
    }
}

"struct" vs "class"

Khi khai báo biến hoặc hàm là static trong struct/class, chúng thuộc về struct/class chứ không thuộc về một đối tượng cụ thể.
Điều này cho phép gọi trực tiếp Permissions::READ, Permissions::setFlag() mà không cần tạo object "Permissions userPerm;"

// "struct" dùng Permission::READ như hằng số, dễ kết hợp bằng toán tử bit.
#include <iostream>

struct Permission
{
    static const int READ  = 1;
    static const int WRITE = 2;
    static const int EXEC  = 4;
};

int main() {
    int userPerm = Permission::READ | Permission::WRITE;
    if (userPerm & Permission::READ) {
        std::cout << "Có quyền đọc\n";
    }
}
// "class" tương tự struct, nhưng có thể kiểm soát phạm vi truy cập.
#include <iostream>

class Permission
{
public:
    static const int READ  = 1;
    static const int WRITE = 2;
    static const int EXEC  = 4;
};

int main() {
    int userPerm = Permission::WRITE;
    if (userPerm & Permission::WRITE) {
        std::cout << "Có quyền ghi\n";
    }
}

"namespace" vs "inline namespace"

Dùng static trong namespace khi bạn muốn hằng số chỉ tồn tại trong file hiện tại (giống như private ở mức file).

// "namespace" cần dùng "::" tránh xung đột tên
#include <iostream>

namespace Permission
{
    static const int READ  = 1;
    static const int WRITE = 2;
    static const int EXEC  = 4;
}

int main() {
    int userPerm = Permission::READ | Permission::WRITE; // phải dùng prefix
    if (userPerm & Permission::WRITE) {
        std::cout << "Có quyền ghi\n";
    }
}
// "inline namespace" không cần dùng "::" cú pháp ngắn hơn
#include <iostream>

inline namespace Permission
{
    static const int READ  = 1;
    static const int WRITE = 2;
    static const int EXEC  = 4;
}

int main() {
    int userPerm = READ | WRITE; // không cần prefix
    if (userPerm & WRITE) {
        std::cout << "Có quyền ghi\n";
    }
}

Ví dụ về chương trình cấp quyền

#include <iostream>
#include <string>

struct Permission {
    static const int READ  = 1;
    static const int WRITE = 2;
    static const int EXEC  = 4;

    // Cấp quyền
    static void grantPermission(int &userPerm, int perm) {
        userPerm |= perm;
    }

    // Thu hồi quyền
    static void revokePermission(int &userPerm, int perm) {
        userPerm &= ~perm;
    }

    // Kiểm tra quyền
    static bool hasPermission(int userPerm, int perm) {
        return (userPerm & perm) != 0;
    }

    // In danh sách quyền hiện có
    static void printPermissions(int userPerm) {
        std::cout << "Quyền hiện có: ";
        if (hasPermission(userPerm, READ))  std::cout << "READ ";
        if (hasPermission(userPerm, WRITE)) std::cout << "WRITE ";
        if (hasPermission(userPerm, EXEC))  std::cout << "EXEC ";
        std::cout << "\n";
    }
};

int main() {
    int userPerm = 0;

    // grant quyền
    Permission::grantPermission(userPerm, Permission::READ);
    Permission::grantPermission(userPerm, Permission::WRITE);
    Permission::printPermissions(userPerm);

    // thu hồi quyền
    Permission::revokePermission(userPerm, Permission::READ);
    Permission::printPermissions(userPerm);

    // kiểm tra quyền
    if (Permission::hasPermission(userPerm, Permission::EXEC)) {
        std::cout << "Có quyền thực thi\n";
    } else {
        std::cout << "Không có quyền thực thi\n";
    }
}
Quyền hiện có: READ WRITE 
Quyền hiện có: WRITE 
Không có quyền thực thi

Xem thêm : https://onlybinh.duckdns.org/bitmasking/

Leave a Comment