PDA

View Full Version : Truy cập đến thành phần private ???



ANHDAY
16-11-2002, 15:16
Làm seo mà truy cập đến thành phần private cua lớp từ bên ngoài, tức là từ bên ngoài làm sao cho hiện ra giá trị của a.x, a.y

xinhochoi
16-11-2002, 16:46
Xin noi ro hon la dung ngon ngu nao.
C: khong co private
C++: su dung methods de access private.
C#: su dung properties.

khôngtên
16-11-2002, 22:08
Đã là private thì không có cách nào truy nhập từ bên ngoài được bạn ạ !

danceswithwolves
17-11-2002, 09:34
nếu tự do truy cập được các private members thì còn đâu là encapsulation nữa. Cũng như khôngtên@, câu trả lời là 'no way'.

xinhochoi
17-11-2002, 12:03
Hm..... "truy cập", tiếng việt có nghĩa là gì??? :rolleyes:

nbthanh
18-11-2002, 17:54
Nếu để "truy cập" thuần tuý thôi thì dùng các method cũng tốt rồi.
Còn nếu bạn muốn một "mẹo" truy cập private properties của 1 class (trong C++) từ bên ngoài thì bạn có thể tham khảo bài viết này http://www.diendantinhoc.org/forum/?action=msg&msg=1023410600#1023410600

CrazyKing
18-11-2002, 18:36
Chào bác ! Bác có thể truy xuất (đọc or ghi ) giá trị của bất kỳ biến thành viên nào kể cả private/protected/public trong class nếu đã biết được cấu trúc của class này !! Ta ví dụ hén :
Ta có class "
class CMyClass
{
private:
int x;
char y;
...
};
Khai báo biến X dùng class này :
CMyClass X;
và 02 biến m.n dùng để lấy dữ liệu private của biến X :
int m;
char n;
...
Khi đó bác truy cập đến nó như sau :
m = * (( (int*) &X)+0); // biến thành viên X.x có độ dài 4 byte, bắt đầu từ byte thứ 0 tính từ địa chỉ của X)
n = * (((char*)&X)+4); // biến thành viên X.y có độ dài 1 byte, bắt đầu từ byte thứ 4 tính từ địa chỉ của X)
* ((int*)&X) = 10; // Gán X.x = 10;
* (((char*)&X)+4) = 0; // Gán X.y = 0;
He he , bác thử làm đi , chắc chắn đúng ! Đến đây chắc đã giải đáp được thắc mắc của bác rùi hí !

nbthanh
18-11-2002, 18:49
Bài viết được gửi bởi CrazyKing chắc chắn đúng ![/B]
99%...sai nếu bạn biết class là gì và cấu trúc của các trình biên dịch. Thử đọc bài này coi chơi: http://www.diendantinhoc.org/forum/?action=msg&msg=1023410607#1023410607
(còn mấy bài khác cũng hay lắm nhưng tôi tạm thời chưa tìm ra, nhưng đại lý là nếu A là 1 class thì chưa chắc là con trỏ đến byte đầu tiên của A sẽ chỉ tới phần tử đầu tiên của A đâu)

xinhochoi
19-11-2002, 03:33
CrazyKing, cách của cậu khá hay nhưng hơi nguy hiểm. Dùng pointer để access memory allocation, đối với CrazyKing đã giỏi về programming C/C++ thi không sao, nhưng đối với người mới thi .... :eek: :confused:
ANHDAY, nếu bác có thử cách của CrazyKing thì đừng thử trong C# vì C# không dùng pointer.

MakeLove
19-11-2002, 08:25
Bác crazyking nói đúng đó !!!! Hổng có sai đâu !

CrazyKing
19-11-2002, 08:33
Bài viết được gửi bởi nbthanh
99%...sai nếu bạn biết class là gì và cấu trúc của các trình biên dịch.
Bác này nói kỳ quá !!!!! Ở đây tui nói m có kiểu là int thì sizeof của nó đương nhiên là 4, còn n có kiểu là char do đó có sizeof là 1 , các biến này có địa chỉ bắt đầu là byte thứ 0 tính từ địa chỉ X cơ mà (Chắc chắn là như vậy)!!!!????Làm sao có chuyện sai ở đây được ??? Còn ở bài viết kia là sự khác nhau do tuỳ chọn giữa biên dịch struct alignment làm tròn theo bội số của 8 , nhưng đó đối với kiểu struct chứ còn ở đây thì int , char thì có liên quan gì ???
Bác đã test chưa mà dám bảo là 99% sai ???

xinhochoi
19-11-2002, 09:32
m = * (( (int*) &X)+0);
n = * (((char*)&X)+4);

----------------------

Cách của CrazyKing không có sai đâu, nbthanh. int là 1 word (4 bytes), char thì 1 byte. Chỉ có điều là nếu có vài variables khác nhau như double, long, float nữa thì ngồi tính số byte để cộng cho đúng thì.... :o :(

nbthanh
19-11-2002, 09:42
Trong C kich thuoc cua du lieu can ban khong co dinh. Tuy thuoc vao he dieu hanh, trinh bien dich ma no co the khac nhau. Tren 1 so may thi char la 1 byt, int la 2 byte. Nhung cung co the tren 1 so may char la 2 byte (unicode chang han) int la 4 byte. Chang han nhu may toi dang ngoi day cai Linux va Wndows. Tren Linux thi int la 32 bit, tren Win thi 2 version cua Borland C de la 16 va 32 bit.
Cho nen dung kich thuoc cua kieu du lieu trong truong hop nay la se sai :D

O quen nua, dia chi bat dau cua class co la 0 hay khong thi con tuy vao trinh bien dich nua!

(sorry, Mozilla khong go duoc TV)

ANHDAY
19-11-2002, 20:16
Cảm ơn anh crazyking nhiều , cách của anh em đã thử rồi , thật hay !

danceswithwolves
21-11-2002, 09:27
thật lòng mà nói các bác thật... "hâm". Chẳng phải ngẫu nhiên mà C++ được Bjarne Stroustrup cung cấp tính năng OO. Dùng cách phi OOP để truy cập private members với sức mạnh (rất nguy hiểm) truy xuất trực tiếp bộ nhớ của C++ là một bước đi... xuống vực. Nếu một trong 3 tính chất Inheritance, Encapsulation hay Polymorphism bị xâm phạm, các bạn đã tự mở một con đường đầy cạm bẫy cho bản thân.

to xinhochoi@ : C# cho phép sử dụng pointer trong đoạn mã unsafe. Tuy nhiên, với những class không bị programmer dùng custom attribute áp đặt tính cố định thứ tự thành viên (class member) thì CLR sẽ tự sắp xếp thứ tự các class member trong managed-heap theo cách mà nó cho là hợp lý nhất -> cách của CK@ cũng không được.

cuối cùng, đưa lại lời của một tác giả IT nổi tiếng là : đừng bao giờ viết ra "such smart code that can make programming rules blew out". Hãy tôn trọng các quy tắc OOP vì chúng sinh ra là để hỗ trợ và bảo vệ cho chúng ta. Lẫn nữa, xin khẳng định là không thể truy cập private members của class :).

anhcntt2000
21-11-2002, 10:18
xin chao ban!
không có gì khó bạn ah!
bạn khai báo một hàm trong đó có từ khóa friend là bạn có thể truy cập vào dược lièn ah

MakeLove
22-11-2002, 08:32
truy xuất trực tiếp bộ nhớ của C++ là một bước đi... xuống vực.

À há !!!! Bác này sao bi quan thế ???
Tại sao lại sợ nó chứ? Phải tìm hiểu chúng , khám phá chúng , chứ sao nghe người ta nên trung thành với OOP thì bác đã trung thành rùi ! Sao bác cả tin thế !!! Thực tế cho thấy tui vẫn lấy được giá trị private đó thui !!! ha ha !!!
Con bác kia ui ! Khai báo thêm từ khóa friend nữa thì còn gì mà nói !!! Bác hiểu lầm câu hỏi của người ta rùi !!!! :rolleyes:

CrazyKing
22-11-2002, 08:44
Nè , tui có giải pháp khác cho ANHDAY nữa đây !!!(Đây là giải pháp của một người bạn tui )
Đọc dữ liệu qua một lớp giả là CPrivateRemover.

class CBaseClass {
private:
int x;
int RunF(int param1);
};
class CPrivateRemover: public CBaseClass {
public:
int GetX() { return x; }
void SetX(int newx) { x=newx; }
int RunF(int param1) { return CBaseClass::RunF(param1); }
};

CBaseClass* pa;
int x, y;
x = ((CPrivateRemover*)pa)->GetX(); // x = pa->x;
((CPrivateRemover*)pa)->SetX(x); // pa->x = x;
y = ((CPrivateRemover*)pa)->RunF(x); // y = pa->RunF(x);

Cách này khá hay đấy chứ ????

danceswithwolves
22-11-2002, 15:49
to ML@ (thông cảm nhé, nick của bạn... cá tính quá nên tớ không muốn viết đầy đủ) :

chính vì những người "thích khai phá" một cách vô tội vạ như cậu mà tính phi OO của các lập trình viên C++ (đặc biệt là những người có background C) được "phát huy" mạnh mẽ. Tớ khuyên đây là để bảo vệ cho một tư tưởng lập trình. Rõ ràng, để nghiên cứu học tập thì chúng ta cứ tự nhiên thí nghiệm smart code; nhưng phải lưu giữ một tư tưởng OO cho các dự án nghiêm túc. Nên nhớ rằng ở box này có khá nhiều những người mới học, cứ mặc sức "phá cách" tràn lan sẽ dẫn đến những khó khăn không cần thiết cho họ. Quả thật tớ sợ, sợ những người như cậu sẽ phá hỏng mục tiêu lớn nhất của box này bởi những kiểu cách "phi thường" của mình.

Cuối cùng, không biết cậu thích chí gì mà cười to đến thế ? CrazyKing@, theo thiển ý của tớ, còn cao tay ấn hơn cậu n lần mà tớ vẫn chưa lần nào thấy hắn cười đắc ý đến vậy...

monkeyvu
05-12-2002, 11:00
anh CrazyKing ơi ,em làm thử cách của anh nhưng mà em +4 đâu có được dzì đâu ,em cộng 2 thì lại được .

nbthanh
06-12-2002, 13:53
Bài viết được gửi bởi monkeyvu
anh CrazyKing ơi ,em làm thử cách của anh nhưng mà em +4 đâu có được dzì đâu ,em cộng 2 thì lại được .
Bạn hãy xem lại các bài viết trước của tôi trong thread này. Như tôi đã lưu ý, các kiểu dữ liệu của C trên mỗi platform và mỗi trình biên dịch có thể khác nhau. Số nguyên (int) trong C có thể 2 byte, có thể 4 byte cũng có thể là....8 byte cũng không chừng! Cho nên cách làm cùa CrazyKing là rất nguy hiểm và tuyệt đối không nên dùng!