30/09/2018, 22:12

Static member của class trong C++

Các anh có thể “thông não” giùm em được không ạ , em vẫn không hiểu lắm về static member trong C++, rồi về toán tử :: trong C++ nữa.

Cảm ơn các anh chị

Tao Không Ngu. viết 00:18 ngày 01/10/2018

This post was flagged by the community and is temporarily hidden.

viết 00:26 ngày 01/10/2018

:: là để truy cập biến, hàm, v.v… trong 1 namespace, hoặc truy cập biến/hàm static của 1 class. Hiểu nó như là toán tử tìm kiếm “người” trong 1 “họ” nào đó vậy. Ví dụ Nguyễn:: thì truy cập những người thuộc họ Nguyễn. Ví dụ lớp có 2 người tên “VănMinh” nhưng khác họ thì mỗi lần gọi là gọi Trần::VănMinh với Nguyễn::VănMinh

static member là của chung. Còn member bình thường là của riêng của đối tượng tạo ra từ class đó. Method bình thường gọi / truy cập hàm/biến static được, nhưng hàm static thì ko gọi được method/biến bình thường

class A
{
public:
    A(int n=0) : val(n) {}
    
    void printVal()const { std::cout << "my (const) val is " << val << "\n"; }
    void printVal() { std::cout << "my val is " << val++ << "\n"; }
    void printSecret()const //chú ý const ở đây nghĩa là hằng A vẫn thay đổi secret được
    { std::cout << "secret = " << secret++ << "\n"; }
public:
    static void setSecret(int n) { secret = n; }
    static int  getSecret() { return secret; }
public:
    static int count; //biến count là của chung, tất cả object có kiểu A đều truy cập được
private:
    static int secret; //secret cũng là của chung nhưng chỉ có member thuộc A mới xài được vì nó private
private:
    int val;
};


int A::count = 100; //khởi tạo A::count
int A::secret = 200; //khởi tạo A::secret, ở đây khởi tạo nên truy cập được A::secret
//A::secret = 300; --> lỗi

int main()
{
    A a1(10);
    const A a2(20);
    
    a1.printSecret(); //in ra 200
    a2.printSecret(); //in ra 201, a2 là const nhưng vẫn thay đổi secret được
    a1.printSecret(); //in ra 202
    
    //val là của riêng, ko ai đụng ai
    a1.printVal(); //in ra 10, gọi hàm printVal()
    a1.printVal(); //in ra 11, gọi hàm printVal()
    a2.printVal(); //in ra 20, gọi hàm printVal()const
    a2.printVal(); //in ra 20, gọi hàm printVal()const
    
    std::cout << "a1.count = " << a1.count << "\n"; //in ra 100
    a1.count += 1000;
    A::count += 900;
    std::cout << "a1.count = " << a1.count << "\n"; //in ra 2000
    std::cout << "a2.count = " << a2.count << "\n"; //in ra 2000
    std::cout << "A::count = " << A::count << "\n"; //in ra 2000
    
    //A::secret += 100; error: ‘int A::secret’ is private
    std::cout << "a1.getSecret() = " << a1.getSecret() << "\n"; //in ra 203
    std::cout << "a2.getSecret() = " << a2.getSecret() << "\n"; //in ra 203
    std::cout << "A::getSecret() = " << A::getSecret() << "\n"; //in ra 203
    A::setSecret(10000);
    std::cout << "a1.getSecret() = " << a1.getSecret() << "\n"; //in ra 10000
    std::cout << "a2.getSecret() = " << a2.getSecret() << "\n"; //in ra 10000
    std::cout << "A::getSecret() = " << A::getSecret() << "\n"; //in ra 10000
}

output

secret = 200
secret = 201
secret = 202
my val is 10
my val is 11
my (const) val is 20
my (const) val is 20
a1.count = 100
a1.count = 2000
a2.count = 2000
A::count = 2000
a1.getSecret() = 203
a2.getSecret() = 203
A::getSecret() = 203
a1.getSecret() = 10000
a2.getSecret() = 10000
A::getSecret() = 10000

nếu xài namespace thì các biến / hàm trong namespace đều là public, thực chất là chả có khái niệm public/private gì trong namespace cả. Đôi khi ta cần hạn chế truy cập vài biến/hàm trong namespace thì phải xài class + private static member.

viết 00:23 ngày 01/10/2018

1 biến static điển hình là std::string::npos được định nghĩa:
static const size_t npos = -1;
npos dùng để kiểm tra xem kết quả tìm kiếm chuỗi có tìm ra hay ko

std::string s = "Hello";
if (s.find("world") != s.npos)
    std::cout << "Found world in " << s << "\n";
else 
    std::cout << "NOT found world in " << s << "\n";

nếu thay s.npos bằng std::string::npos cũng được nhưng quá dài, nếu thay bằng -1 thì ko chắc, lỡ có thư viện nào chơi đểu định nghĩa npos = -2 thì kiểm tra -1 ko đúng. Với lại giá trị trả về của s.find(...)size_t, nghĩa là số nguyên ko dấu thì kiểm tra với -1 là số nguyên có dấu thì ko “đúng” cho lắm.

Nguyễn Tấn Khoa viết 00:27 ngày 01/10/2018

Anh giải thích thêm cho em về cách tạo namespace và cách sử dung của nó được không ạ? Em cảm ơn

Tao Không Ngu. viết 00:16 ngày 01/10/2018

This post was flagged by the community and is temporarily hidden.

Phương Trọng Lê viết 00:21 ngày 01/10/2018

Cách tạo namespace thì bạn có thể search trên mạng sẽ đầy đủ hơn, ở đây mình nói ngắn gọn về cách sử dụng của nó.
Giả sử bạn viết 1 function nhưng function đó đã tồn tại trước đó rồi nhưng bạn k thể nào đổi tên function được vì nếu đổi tên sẽ không thể hiện được chức năng của function đó, vậy làm thế nào để giải quyết vấn đề trên. Chúng ta có cách giải quyết đơn giản đó là đưa function đó vào chịu sử quản lý của namespace, 2 function cùng tên nhưng chịu sử quản lý của 2 namespace khác nhau thì không ảnh hưởng gì tới nhau cả.

viết 00:18 ngày 01/10/2018

cách tạo đơn giản lắm, bao xung quanh mấy cái hàm bằng namespace là được.

#include <iostream>


namespace mymathlib
{
typedef double (*UnaryRealFunc)(double); //định nghĩa kiểu của hàm số thực f(x)

double fog(UnaryRealFunc, UnaryRealFunc, double);
double pow(double, unsigned);
}


double f(double x) { return x*x; }
double g(double x) { return x*2; }

int main()
{
    std::cout << mymathlib::fog(f, g, 10) << "\n"; //in ra 400
    std::cout << mymathlib::pow(2.5, 5) << "\n"; //in ra 97.6562
}


namespace mymathlib //bao namespace xung quanh
{
double fog(UnaryRealFunc f, UnaryRealFunc g, double x) //khỏi cần mymathlib::
{
    return f(g(x));
}
}

double mymathlib::pow(double x, unsigned n) //khỏi cần bao namespace xung quanh
{
    if (n == 0) return 1;
    return pow(x,n/2) * pow(x,n/2) * (n%2 ? x : 1);
}
Bài liên quan
0