Tại sao cần tạo class trong c++

View Full Version : Tại sao có struct rồi còn sinh ra class. Lợi thế của class là gì?



car0ot

21-10-2008, 11:11 PM

Đúng như title , em muốn hiểu kỹ hơn sự khác biệt giữa struct và class , mong ae chỉ điểm .

Em đã search trên 4rum nhưng ko thấy ! Thanks


meoconlongvang

21-10-2008, 11:18 PM

struct là một class đặc biệt, các thành viên của nó đều là public


dieucay555

21-10-2008, 11:27 PM

Quan trọng là struct thì không thể OOP như là class.


Lugiavn

22-10-2008, 12:56 AM

Struct là 1 loại kiểu dữ liệu có tác dụng gom các thằng kiểu dữ liệu khác vào trong 1 cục cho dễ xử.
Còn class ko đơn giản như vậy, thường thì class sẽ hide hết các dữ liệu bên trong, chỉ chừa cái interface ở ngoài, nên xài class thì đếch cần biết bên trong nó là cí rì. Class có mấy cái như method, inheritance, polymophism... nói chung là OOP, struct hông có mấy cái này (thật ra trong C++ bây giờ hình như cũng struct cũng có method này nọ là do nó bắt chước class chứ nguyên căn là hông có).

Ngôn ngữ như Java, C# toàn là đối tượng, function là method của class hết. Ko có class là ko có gì hết :D


ZCoder87

22-10-2008, 07:59 AM

Lâu lắm rồi mới thấy được câu hỏi hay như vầy!

Class chính là Struct.

Thậm chí vẫn có thể code được cả inheritance, polymorphism trên struct. (dĩ nhiên là không dùng từ khóa public của C++)

Vẫn chưa có ai trả lời thuyết phục câu này cả.


meoconlongvang

22-10-2008, 08:16 AM

Thì class và struct đều như nhau chỉ khác là struct thì luôn public mọi thứ, class thì có thêm private, protected.


tienlbhoc

22-10-2008, 08:22 AM

struct nhẹ hơn class đó , nếu không yêu cầu gì nhiều thì nên dùng struct ở những chỗ không cần rờ tới class với chương trình lớn :)


Lugiavn

22-10-2008, 09:03 AM

Lâu lắm rồi mới thấy được câu hỏi hay như vầy!
Class chính là Struct.
Thậm chí vẫn có thể code được cả inheritance, polymorphism trên struct. (dĩ nhiên là không dùng từ khóa public của C++)

Vẫn chưa có ai trả lời thuyết phục câu này cả.

Mình bảo rồi, nguyên căn struct là 1 cục gom dữ liệu thôi, mà chính xác hơn là trong C. Đến C++ thì có class và mấy cái tính năng mới như method hay inheritance, polymorphism thì struct dc thể ăn theo nên mới có những cái này. Cho nên trong C++ thì struct và class chỉ khác nhau ở chỗ như bác mèo nói là class có private, protected.
Thật ra chẳng ai dùng struct để làm 3 cái chuyện inheritance, polymorphism cả, cho nên nói struct thì ta nên hiểu là struct trong C. Class dc coi là bản nâng cấp struct.

http://en.wikipedia.org/wiki/C%2B%2B_structures_and_classes


rox_rook

22-10-2008, 09:53 AM

- Internal của STL function object đều là struct.
- Cơ bản khác nhau thì chỉ như mèo nói, còn về template và generic thì còn khác nhiều nữa, có những chỗ bắt buộc dùng struct và có những chỗ bắt buộc dùng class.
- Ví dụ 1 function object là cái mà C++ programmer phải viết hằng ngày và tất cả đều là struct ;)

#include <iterator>
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <cmath>

template< typename T1, typename T2 >
struct fopow : public std::binary_function< T1, T2, T1 > {
T1 operator()( T1 bse, T2 exp ) const {
return std::pow( bse, exp );
}
};

int main() {
std::vector< int > v;
for( int o = 1; o <= 9; ++o ) {
v.push_back( o );
}

std::transform( v.begin(), v.end(),
std::ostream_iterator< float >( std::cout, " " ),
bind2nd( fopow< float, int >(), 3 )
);

return 0;
}


DKhanh

22-10-2008, 10:34 AM

Lâu lắm rồi mới thấy được câu hỏi hay như vầy!

Class chính là Struct.

Thậm chí vẫn có thể code được cả inheritance, polymorphism trên struct. (dĩ nhiên là không dùng từ khóa public của C++)

Vẫn chưa có ai trả lời thuyết phục câu này cả.

Vậy bạn trả lời đi.
Theo mình thì struct thì hướng cấu trúc, class thì hướng đối tượng


rox_rook

22-10-2008, 10:37 AM

-> Đối với template, struct và class không như nhau.
-> Còn lại ( non-generic C++ ) là như nhau, vấn đề style thôi ! That's it !


Lugiavn

22-10-2008, 10:44 AM

- Internal của STL function object đều là struct.
- Cơ bản khác nhau thì chỉ như mèo nói, còn về template và generic thì còn khác nhiều nữa, có những chỗ bắt buộc dùng struct và có những chỗ bắt buộc dùng class.
- Ví dụ 1 function object là cái mà C++ programmer phải viết hằng ngày và tất cả đều là struct ;)

Mình chưa học STL và bây giờ mới biết function object ở trên. Giả sử mình mà gặp đoạn code trên (lúc chưa biết nó là cái gì) thì chắc chắn sẽ phải nói "Hết chuyện hay sao mà xài struct ở đây hả trời?" (:#)

Nói thật là đoạn code trên hoàn toàn có thể viết thành class bình thường và đáng lẽ nên viết là class. Mình ko hiểu lắm, bạn chỉ lại đoạn "có những chỗ bắt buộc dùng struct và có những chỗ bắt buộc dùng class" rõ hơn dc ko? (:-)??


rox_rook

22-10-2008, 10:47 AM

Ví dụ đơn giản nhất :

#include <iostream>

template< struct C >
void doSothing( const C& v ) {
std::cout << v << "\n";
}

int main() {
return 0;
}

Try to run it ;) !


Lugiavn

22-10-2008, 10:59 AM

Ví dụ đơn giản nhất :

#include <iostream>

template< struct C >
void doSothing( const C& v ) {
std::cout << v << "\n";
}

int main() {
return 0;
}

Try to run it ;) !

Oạch, chạy ko dc. Cái chỗ template < struct C > là sai mà.
Keyword dùng ở chỗ này fải là class hoặc typename. Nói chung cũng như vấn đề về syntax thôi người ta quy định vậy, chứ chữ class dùng ở đây có liên wan gì đến struct hay class đâu, phỏng ạ (:-)w (:-)w


ZCoder87

22-10-2008, 11:15 AM

template< typename T1, typename T2 >
struct fopow : public std::binary_function< T1, T2, T1 > {
T1 operator()( T1 bse, T2 exp ) const {
return std::pow( bse, exp );
}
};

RR bị phạm luật rồi.

Từ khóa public chỉ có ở C++ thôi. Và struct này chạy với IDE C++ chạy mới hiểu. Chứ nguyên thủy của C thì không có chuyện kế thừa như thế này.

Thật ra chẳng ai dùng struct để làm 3 cái chuyện inheritance, polymorphism cả, cho nên nói struct thì ta nên hiểu là struct trong C. Class dc coi là bản nâng cấp struct.

Bạn nhầm rồi đó. Một trong những công ty vẫn còn sử dụng cách lập trình C mà không dùng C++ để viết phần mềm chính là Microsoft đó. Hệ điều hành Windows chủ yếu viết bằng C vì Windows chạy sát hệ thống.

Thông thường lập trình HDT thì ta vẫn dùng:

C++ Languge:

A *a = new A();
a->Func1();
a->Func2();
...
delete a;

C Languge:

Handle a = Create();
Func1( a );
Func2( a );
Destroy (a)

Bây giờ đa hình

C++ Languge:

class I{
....
virtual void Func1() = 0;
};

class A:public I {
public:
void Func1(){...}
};

class B:public I {
public:
void Func1(){...}
};

I *a = new A();
I *b = new B();

a->Func1();
b->Func1();

delete a;
delete b;

C Languge:

#define CLASSA 1
#define CLASSB 2

Handle a = Create( CLASSA );
Handle b = Create( CLASSB );

// Đa hình
Func1( a );
Func1( b );

Destroy (a)
Destroy (b)

Cái giá trị HWND, HANDLE... của window là đại diện.

Vậy bí quyết để giải quyết vấn đề OOP in C vẫn là ở chỗ: Handle

- Cái này mấy ông Việt Nam dịch là "thẻ điều quản" -> Không hiểu nỗi ý nghĩa
- Nhưng thực tế thì typedef Handle void*

Vì vậy handle chỉ vị trí bộ nhớ của struct...

Vậy cài đặt cái struct này như thế nào thì bạn hãy tiếp tục học đi... lên phần COM/COM+ Programing thì sẽ rõ.... lúc đó bạn làm 1 struct ở C mà các ngôn ngữ như C#, Java có thể dịch được thành class.

Class ra đời nhằm đơn giản đi quá trình code này: Nhưng khi biên dịch thì nó vẫn sẽ chuyển xuống struct của C rồi thành mã máy.

Và do đó dù gì đi nữa thì C++ và C vẫn là 1 (chỉ khác cách code) chứ không như C# và C++.


rox_rook

22-10-2008, 11:16 AM

Oạch, chạy ko dc. Cái chỗ template < struct C > là sai mà.
Keyword dùng ở chỗ này fải là class hoặc typename. Nói chung cũng như vấn đề về syntax thôi người ta quy định vậy, chứ chữ class dùng ở đây có liên wan gì đến struct hay class đâu, phỏng ạ
Sửa/Xóa bài viết- Ủa vậy tui nói khác chỗ nào ? Tui đã nói y như mèo nói struct và class là như nhau chỉ khác cái qualifier thôi !!
- Chỉ có trong template nó có 1 số qui định syntax thôi ! Mà syntax không phải khác chứ là gì ?

RR bị phạm luật rồi.- r2 không hề nói về C. r2 nói về C++.

Và do đó dù gì đi nữa thì C++ và C vẫn là 1 (chỉ khác cách code) chứ không như C# và C++.C++ is a subset of C ;) !


linhdeptrai

24-10-2008, 12:03 PM

tôi chỉ thêm chút bổ sung
Tính chất lịch sử phát triển mà có cả struct và class (C++ dc phát triển lên từ C) và khái niệm class dc mở rộng từ struct. Đây đúng là sự chuyển mình từ lập trình cấu trúc sang hướng đối tượng đúng như MATH-INFO nói ... :P
@rox_rook :
Đúng là cái template này thật là khó hủi .... (hix vẫn chưa có thời gian mà đọc !) tôi còn nhớ struct bên C# dc cấp phát bộ nhớ trực tiếp thì phải. Liệu có đúng với C++ không ? và nếu đúng thì có phải vì thế mà cái ví dụ của cậu phải là struct thì mới work ?... (some intructions ..ps)


zkday2686

24-10-2008, 12:36 PM

đúng nhìn từ góc độ code thì có thể cói struct là class của C++. Nhưng nhìn từ góc độ thiết kế thì nó lại khác.
ví dụ: struct nó không có tính HDT tức bạn thiết kế một struct có tên xxx và bỏ vào chương trình chạy với một đống vớ vẫn các loại thì chẳng ai mà cười bạn cả.
nhưng qua bên class thì khác. bạn không thể thiết kế ra một class với cái tên là Cxxx sau đó quăng vào cho nó cái gì thì quăng được vì sau này bạn còn dùng lại nó ở một cấp độ khác nữa -:P

ví dụ bạn làm một struct như sau:

struct laixe
{
char* ht;
float lương;
int banglai; // loại 1,2,3...
};
struct nhanvien
{
char *ht;
float lương;
}

nhưng khi làm qua class thì chẳng ai lại đi thiết kế 2 class laixe và nhanvien nó có các thuộc tính giống như struct cả.:)

nó sẽ làm:

class nhanvien
{
protected:
char *ht;
float lương;
public:
....
}

class laixe:nhanvien
{
private:
int banglai; // loại 1,2,3...
public:
.....
}

nói chung là class nó sẽ mô tả cho một vật ngoài thế giới thực còn struct thật ra nó là một kiểu gom nhóm để giải quyết vấn đề cho nó gọn hơn thui;)
bản chất của 2 thằng này là khác nhau hoàn toàn :)

Người ta đưa ra class là để cho sau này bạn có ý nâng cấp chương trình lên hay dùng lại code của project trước đó mình làm nó dễ hơn thui.


rox_rook

24-10-2008, 03:40 PM

- struct trong C++ không như zkday nói, nó và class là 1.
- Cái chỉ có dữ liệu là POD( plain old data ) và class trong C++ cũng có thể có được điều này, dùng từ khóa public là ok hết.
- Struct trong C++ vẫn kế thừa được như class.
- Everything is the same, just the matter of style.


ZCoder87

24-10-2008, 04:21 PM

zkday hoàn toàn sai rồi!

Không có gốc thì không thể có ngọn. Và nếu không có struct thì sẽ không bao giờ có class cả???

Sẵn tiện đây mình sẽ giải thích cụ thể vấn đề này luôn.

Giải sử mình đang ở thập nhiên 80 (lúc đó chỉ có ngôn ngữ C)

Mình sẽ code class như thế nào?

struct ZTagNhanvien
{
// Member function
struct vftable
{
void (*Nhap)(ZTagNhanvien*);
void (*Xuat)(ZTagNhanvien*);
};

vftable __vfptr;
// Member variable
char m_lpHoten[200];
int m_nTuoi;
int m_nLuong;
};

Đó chính xác là 1 class đó.
Class chỉ lưu các biến thành viên và 1 bảng con trỏ các hàm thành viên.

Vì hàm thành viên được lưu như vậy nên đây mới là nguyên tắc của sự kế thừa.

Bây giờ mình sẽ định nghĩa các hàm thành viên của nó:

// Nhap
void Nhanvien$$Nhap(ZTagNhanvien* pThis)
{
printf ("Nhap ten nhan vien: ");
gets( pThis->m_lpHoten );

printf ("Nhap tuoi nhan vien: ");
scanf( "%d", &pThis->m_nTuoi );

printf ("Nhap luong nhan vien: ");
scanf( "%d", &pThis->m_nLuong );
}

// Xuat
void Nhanvien$$Xuat(ZTagNhanvien* pThis)
{
printf ("Ho ten: %s\n", pThis->m_lpHoten );
printf ("Tuoi : %d\n", pThis->m_nTuoi);
printf ("Luong : %d\n", pThis->m_nLuong);
}

// Constructor
void Nhanvien$$Nhanvien(ZTagNhanvien* pThis)
{
pThis->__vfptr.Nhap = &Nhanvien$$Nhap;
pThis->__vfptr.Xuat = &Nhanvien$$Xuat;
}

Constructor sẽ gán hàm thành viên vào.

Dấu $$ chỉ là ký tự bình thường thôi. Nếu bạn nào biết Dump file DLL thì sẽ thấy function nó lưu dưới dạng <classname>@@?<FunctionName>...

Đây là danh sách các hàm Public:

typedef void* handle;

Handle Create_NhanVien()
{
ZTagNhanvien *r = (ZTagNhanvien*) malloc( sizeof(ZTagNhanvien) );

// Goi Constructor
Nhanvien$$Nhanvien( r );

return (Handle)r;
}

void Destroy_NhanVien(Handle h)
{
free (h);
}

// Public function
void Nhap( Handle h )
{
ZTagNhanvien *p = (ZTagNhanvien*) h;
p->__vfptr.Nhap( p );
}

void Xuat( Handle h )
{
ZTagNhanvien *p = (ZTagNhanvien*) h;
p->__vfptr.Xuat( p );
}

Lúc này đối tượng được chuyển thành Handle, có nghĩa là mình đã protected các member của class lại rồi.


ZCoder87

24-10-2008, 04:23 PM

Hàm Main như thế này nhé:

int main()
{
Handle nv;

// Khoi tao nhan vien
nv = Create_NhanVien();

Nhap(nv);
Xuat(nv);

// Huy nhan vien
Destroy_NhanVien( nv );

return 1;
}

Bây giờ là kế thừa!

ZTagNhanvienketoan kế thừa ZTagNhanvien

struct ZTagNhanvienketoan
{
// Inherit function .... (virtual)
struct vftable
{
void (*Nhap)(ZTagNhanvienketoan*);
void (*Xuat)(ZTagNhanvienketoan*);
};
vftable __vfptr;

// Inherits
ZTagNhanvien m_Base;

// Member variable
char m_lpPhongban[100];

// Member function
// ...
// ...
};

Kế thừa chính là nó chứa struct cha!

Lưu ý 1 điều:
- Bảng danh sách các hàm virtual phải ở trên cùng (nguyên tắc để đa hình)
- Sau đó là đối tượng cha
- Rồi mới tới thành viên của nó.

Các hàm thành viên của Ketoan

// Nhap thong tin nhan vien
void Nhanvienketoan$$Nhap(ZTagNhanvienketoan* pThis)
{
// Base Function
pThis->m_Base.__vfptr.Nhap( &pThis->m_Base );

fflush( stdin );
printf ("Nhap phong ban: ");
gets( pThis->m_lpPhongban );
}

// Xuat thong tin nhan vien
void Nhanvienketoan$$Xuat(ZTagNhanvienketoan* pThis)
{
pThis->m_Base.__vfptr.Xuat( (ZTagNhanvien*) &pThis->m_Base );

printf ("Phong ban: %s", pThis->m_lpPhongban);
}

void Nhanvienketoan$$Nhanvienketoan(ZTagNhanvienketoan* pThis)
{
// Base Constructor
Nhanvien$$Nhanvien( &pThis->m_Base );

// Constructor
pThis->__vfptr.Nhap = &Nhanvienketoan$$Nhap;
pThis->__vfptr.Xuat = &Nhanvienketoan$$Xuat;
}

Tiếp là public hàm khởi tạo

// Contructor
Handle Create_NhanVienKeToan()
{
ZTagNhanvienketoan *r = (ZTagNhanvienketoan*) malloc( sizeof(ZTagNhanvienketoan) );
Nhanvienketoan$$Nhanvienketoan ( r );
return (Handle)r;
}

// Destructor
void Destroy_NhanVienKeToan(Handle h)
{
free (h);
}

Và hàm Main:

int main()
{
Handle nv,nvkt;

nvk1 = Create_NhanVienKeToan();
nv = Create_NhanVien();

// Đa hình chỗ này!!!

// Nhap xuat nv
Nhap(nv);
Xuat(nv);

// Nhap xuat nvkt
Nhap(nvkt);
Xuat(nvkt);

Destroy_NhanVienKeToan( nvkt );
Destroy_NhanVien( nv );
return 1;
}


zkday2686

24-10-2008, 04:40 PM

Đúng như zcoder nói các struct và con trỏ hàm nó là cơ sở để tạo nên class trong C++ và tính "Đa hình" trong nó. và nó là cái hay nhất và đẹp nhất ở C++ mà zkday từng biết.

theo như zkday được biết thì các Compiler C++ nó dùng kiểu như zcoder làm để quản lý các phương thức virtual và biết lúc nào thì cần phải gọi cái phương thức của class nào.

đúng là zkday có nhầm lẫn một vài vấn đề của struct bên C và bên C++ như zcoder và r2 nói.


Lugiavn

24-10-2008, 04:40 PM

Mình từng xài struct trong C để mô phỏng có method như class này nọ, nhưng làm luôn inheritance với polymophysm của class như trên thì quả là ghê.
Chắc class dc xây dựng từ struct theo kiểu ZCoder ghi ở trên. Nên nói class là bản mở rộng của struct mà :D


ZCoder87

24-10-2008, 04:41 PM

Vậy tại sao đa hình.
Mình không code lại hàm Nhap(Handle) và Xuat(Handle)

Vì trên bộ nhớ sẽ lưu đối tượng như sau:

Nhanvienketoan:
[ [Base] | <Nhan vien ke toan member> ]

Base chính là vùng data của Nhanvien

Còn

Nhanvien
[<member function> < Nhanvien member> ]

Do đó nếu ta ép kiểu void* thì nó sẽ chuyển thành Nhanvien rất dễ dàng.
Hơi trừu tượng nhưng suy ngẫm thì sẽ hiểu đó.

Không biết có ai có ý kiến gì không?

Class ra đời để đơn giản quá trình code này.
Thấy code kiểu này lằng nhằng không??


NamVoDang

24-10-2008, 05:26 PM

Struct trong C++ đã biến thái so với C :D.


vBulletin® Version 4.2.2, Copyright © 2022 vBulletin Solutions, Inc. All rights reserved. Administer by Kevin Hoang