Trong hướng dẫn C / C ++ trung cấp này, bạn sẽ học cách mang một số phong cách lập trình hướng đối tượng sang C, một ngôn ngữ không có hỗ trợ OOP tích hợp sẵn.
Bạn đang xem : cách tạo đối tượng trong c
Tổng quan h2>
Các ngôn ngữ lập trình như C ++ và Java có hỗ trợ tích hợp cho các khái niệm OOP. Tuy nhiên, bạn có biết rằng bạn không cần sử dụng ngôn ngữ OOP để sử dụng kiểu OOP và nhận được một số lợi ích của lập trình hướng đối tượng? Trong hướng dẫn này, tôi sẽ giải thích cách chúng ta có thể mang một số phong cách lập trình hướng đối tượng sang C, một ngôn ngữ không có hỗ trợ OOP tích hợp sẵn.
Các loại đơn giản, không đa hình
Hãy xem xét một lớp đơn giản không thể bị ghi đè (không có phương thức ảo):
class
Điểm
{
công khai
:
Point ( int
x, int
y);
~ Điểm ();
int
x
()
const
;
int
y
()
const
;
riêng tư
:
const
int
x_;
const
int
y_;
};
Point :: Point ( int
x, int
y): x_ (x), y_ (y) { }
Điểm :: ~ Điểm () {}
int
Điểm :: x
()
const
{ return
x_; }
int
Điểm :: y
()
const
{ return
y_; }
Tiêu đề cho điều này có thể được dịch sang C như sau:
struct
Điểm
;
Point *
Point__create
(
int < / p> x,
int
y) ;
void
Point__destroy
(Điểm * bản thân)
;
int
Point__x
(Điểm * bản thân)
;
int
Point__y
(Điểm * bản thân)
;
Có một số điểm quan trọng cần lưu ý về bản dịch này. Thứ nhất, chúng tôi không chỉ rõ định nghĩa đầy đủ của “Point” để đạt được tính đóng gói; chúng tôi giữ “x” và “y” một cách hiệu quả là “riêng tư” bằng cách xác định đầy đủ “Điểm” chỉ trong tệp nguồn. Thứ hai, chúng tôi tạo các hàm tương ứng với hàm tạo / hủy cộng với cấp phát / định vị thỏa thuận thay thế “mới” và “xóa”. Thứ ba, tất cả các hàm thành viên nhận được một tham số rõ ràng là “self” của kiểu đang được vận hành (thay thế cho tham số ngầm “this”).
Tệp nguồn cho các khai báo ở trên có thể giống như sau:
struct
Điểm
{
int
x;
int
y;
};
void
Point__init
(Point * self,
int
x, int
y) {
tự- & gt; x = x;
tự & gt; y = y;
}
Point *
Point__create
(
int < / p> x,
int
y) {
Point * result = (Point *) malloc
( sizeof
(Point));
Point__init (kết quả, x, y);
trả về kết quả
;
}
void
Point__reset
(Điểm * bản thân)
{
}
void
Point__destroy
(Điểm*
point
) {
if
( point
) {
Point__reset ( point
);
free
( point
);
}
}
int
Point__x
(Điểm * bản thân)
{
trả về
self- & gt; x;
}
int
Point__y
(Điểm *
point
) {
trả về
tự & gt; y;
}
Các mẫu áp dụng cho các đối tượng đơn giản cũng được áp dụng cho các loại đối tượng khác, nhưng chúng tôi thêm một số cải tiến để giải quyết các khái niệm như đa hình và kế thừa.
Các loại đa hình
Để tạo các kiểu đa hình trong C, chúng ta cần bao gồm thông tin kiểu bổ sung trong các đối tượng của mình và chúng ta cần một số cách ánh xạ từ thông tin kiểu đó đến tùy chỉnh mà kiểu yêu cầu. Để minh họa điều này, hãy xem xét:
class
Hình dạng
{
công khai
:
ảo
~ Hình dạng () {}
ảo
const
char
* name
()
const p>
= 0
;
ảo
int
các bên
()
const
= 0
;
};
class
Hình vuông
: công khai
Hình dạng {
công khai
:
Hình vuông ( int
x, int
y, int p > width,
int
height)
: x_ (x), y_ (y), width_ (chiều rộng), height_ (chiều cao) {}
virtual
~ Square () {}
const
char
* tên
()
const
ghi đè p>
{ return
"Hình vuông"
; }
int
bên
()
const
ghi đè
{ trả về
4
; }
int
x
()
const
{ return
x_; }
int
y
()
const
{ return
y_; }
int
width
()
const
{ return
width_; }
int
height
()
const
{ return
height_; }
riêng tư
;
int
x_;
int
y_;
int
width_;
int
height_;
};
Đối với lớp cơ sở Shape, chúng ta có thể khai báo mã C sau:
struct
Hình dạng
;
struct
ShapeType
;
ShapeType *
ShapeType__create
(
int
buffer_size,
const
char
* (* name) (Shape *),
int
(* bên) (Hình dạng *),
void
(* tiêu diệt) (Hình dạng *)) ;
Shape *
Shape__create
(ShapeType * type)
;
ShapeType *
Shape__type
(Hình dạng * tự)
;
void
* Shape__buffer
(Hình dạng * bản thân)
;
int
Shape__sides
(Hình dạng * bản thân)
;
void
Shape__destroy
(Hình dạng * hình dạng)
;
Trong đoạn mã trên, hãy lưu ý rằng chúng tôi đã tạo một đối tượng bổ sung đại diện cho kiểu của hình dạng. Thông tin loại này là cách chúng tôi thực hiện điều phối động (tức là cách chúng tôi giải quyết các chức năng ảo). Bạn cũng sẽ lưu ý điều thú vị về “kích thước” này, chúng tôi sử dụng để cho phép Hình dạng được phân bổ thêm không gian cho bộ đệm, chúng tôi sẽ sử dụng để lưu trữ dữ liệu cho lớp con của hình dạng.
Ý tưởng cơ bản là đối với mỗi loại hình (Hình vuông, Hình ngũ giác, Hình lục giác, v.v.), sẽ có chính xác một phiên bản của cấu trúc ShapeType
. Có nghĩa là, mọi Square
mà chúng tôi tạo sẽ tham chiếu đến cùng một trường hợp chính xác của ShapeType
đại diện cho các hình vuông.
Mã triển khai tương ứng cho lớp cơ sở có thể giống như sau:
struct
Hình dạng
{
Kiểu ShapeType *;
char
buffer_start;
};
struct
ShapeType
{
int
buffer_size;
const
char
* (* name) (Hình dạng *);
int
(* bên) (Hình dạng *);
void
(* tiêu diệt) (Hình dạng *);
};
ShapeType *
ShapeType__create
(
int
buffer_size,
const
char
* (* name) (Shape *),
int
(* bên) (Hình dạng *),
void
(* tiêu diệt) (Hình dạng *)) {
ShapeType * result = (ShapeType *) malloc
( sizeof
(ShapeType));
result- & gt; buffer_size = buffer_size;
kết quả- & gt; name = name;
kết quả- & gt; bên = bên;
kết quả- & gt; tiêu diệt = tiêu diệt;
trả về kết quả
;
}
Shape *
Shape__create
(ShapeType * type)
{
int
size
= sizeof
(Hình dạng) + type- & gt; buffer_size;
Hình dạng * result = (Hình dạng *) malloc
( size
);
kết quả- & gt; type = type;
trả về kết quả
;
}
ShapeType *
Shape__type
(Hình dạng * tự)
{
return
self- & gt; type;
}
void
* Shape__buffer
(Hình dạng * bản thân)
{
return
( void
*) & amp; (self- & gt; buffer_start);
}
int
Shape__sides
(Hình dạng * bản thân)
{
return
self- & gt; type- & gt; side (self);
}
void
Shape__destroy
(Hình dạng * hình dạng)
{
nếu
(shape) {
shape- & gt; type- & gt; kill (shape);
}
}
Chức năng của lớp cơ sở có thể trở nên rõ ràng hơn khi chúng ta xem xét một trường hợp dẫn xuất. Khai báo cho một hình vuông có thể giống như sau:
// square.h
struct Square;
Shape * Square__to_shape (Hình vuông * hình vuông);
Square * Square__from_shape (Hình dạng * hình dạng);
Square * Square__create (int x, int y, int width, int height);
void Square__destroy (Square * hình vuông);
// Tương tự với các trình truy cập trong trường hợp trước
int Square__x (Hình vuông * tự);
int Square__y (Vuông * tự));
int Square__width (Hình vuông * tự);
int Square__height (Hình vuông * tự);
Và định nghĩa tương ứng của nó:
// square.c
struct SquareData {
int x;
int y;
chiều rộng int;
chiều cao int;
};
const char * Square__name_override (Hình dạng * tự) {
return "Hình vuông";
}
int Square__sides_override (Hình dạng * tự) {
trả về 4;
}
void * Square__destroy_override (Hình dạng * hình vuông) {
miễn phí (hình vuông);
}
static ShapeType * square_type =
ShapeType__create (
sizeof (SquareData),
& amp; Square__name_override,
& amp; Square__sides_override,
& amp; Square__destroy_override);
Hình dạng * Square__to_shape (Hình vuông * hình vuông) {
return ((Hình dạng *) hình vuông);
}
Square * Square__from_shape (Hình dạng * hình dạng) {
if (! shape) {
return ((Hình vuông *) 0);
}
ShapeType * type = Shape__type (hình dạng);
if (type! = square_type) {
return ((Hình vuông *) 0);
}
return ((Hình vuông *));
}
SquareData * Square__square_data (Square * tự) {
Shape * shape = (Hình dạng *) tự;
return (SquareData *) Shape__buffer (hình dạng);
}
Square * Square__create (int x, int y, int width, int height) {
Square * result = (Vuông *) Shape__create (kiểu_bình vuông);
SquareData * square_data = Square__square_data (kết quả);
dữ liệu hình vuông- & gt; x = x;
dữ liệu hình vuông- & gt; y = y;
dữ liệu hình vuông- & gt; width = width;
square_data- & gt; height = height;
trả về kết quả;
}
void Square__destroy (Square * hình vuông) {
Shape__destroy (Square__to_shape (hình vuông));
}
int Square__x (Hình vuông * tự) {
return Square__square_data (self) - & gt; x;
}
int Square__y (Hình vuông * tự) {
return Square__square_data (self) - & gt; y;
}
int Square__width (Hình vuông * tự) {
return Square__square_data (self) - & gt; width;
}
int Square__height (Hình vuông * tự) {
return Square__square_data (self) - & gt; height;
}
Để tóm tắt đoạn mã trên, khi liên quan đến kế thừa / đa hình, cần phải đóng gói các hàm đa hình trong một cấu trúc đại diện cho các kiểu dẫn xuất khác nhau của kiểu cơ sở. Bởi vì các kiểu dẫn xuất cũng có thể thêm nhiều dữ liệu hơn vào đối tượng, thao tác cấp phát phải cho phép các kiểu dẫn xuất yêu cầu thêm không gian. Cũng cần cung cấp các hàm có thể thực hiện truyền lên và truyền xuống giữa các kiểu dữ liệu khác nhau. Ngoài ra, các hàm ảo trong C ++ dịch sang các hàm tìm kiếm và gửi đến việc triển khai theo kiểu được cung cấp của hàm đã cho.
Với những điều trên, bạn có thể hỏi, tại sao lại có thêm lớp chuyển hướng của ShapeType
? Tại sao không chỉ cần lưu trữ các con trỏ hàm đại diện cho hàm ảo ghi đè trực tiếp trên đối tượng Shape
(sẽ được cung cấp trong hàm create
của các loại dẫn xuất khác nhau).
Điều này được thực hiện vì hiệu quả … việc kết hợp các chức năng ảo khác nhau ghi đè trong một đối tượng loại tồn tại lâu dài riêng biệt cho phép mỗi phiên bản chỉ trả cho một trường con trỏ duy nhất để hỗ trợ tính đa hình; nếu dữ liệu này trực tiếp trên các phiên bản, thì mỗi phiên bản sẽ cần nhiều trường bổ sung vì có các hàm ảo.
Kết luận
Có thể kết hợp dữ liệu với hành vi, đóng gói các trường dữ liệu, kế thừa / đa hình và các khái niệm OOP khác có thể đạt được trong các ngôn ngữ lập trình thiếu hỗ trợ OOP (như C), mặc dù có nhiều bản soạn thảo hơn. Điều này sẽ có ý nghĩa trực quan vì các ngôn ngữ OOP phải / phải được triển khai theo các ngôn ngữ không phải OOP tại một số thời điểm. Mặc dù, trong một số trường hợp, bảng soạn sẵn mà cách tiếp cận này tạo ra có thể không phải lúc nào cũng đáng giá, việc viết mã C bắt buộc theo kiểu OOP có thể làm sáng tỏ cách hoạt động của OOP. Khả năng viết theo kiểu này cũng có giá trị để tạo các API được chia sẻ giữa các ngôn ngữ OOP và không phải OOP.
Xem thêm những thông tin liên quan đến chủ đề cách tạo đối tượng trong c
[C++] – Bài 48: Constructors – Hàm tạo.
- Tác giả: thân triệu
- Ngày đăng: 2016-07-01
- Đánh giá: 4 ⭐ ( 7041 lượt đánh giá )
- Khớp với kết quả tìm kiếm: Hướng dẫn lập trình C++ căn bản. tự học lập trình. classes and objects: hàm tạo của class trong C++. triệu thân channel – let’s grow together!.
link file .cpp: http://adf.ly/1jQPyR
file .pptx: http://adf.ly/1jQPEf
Tìm hiểu C# và ứng dụng: Lớp và đối tượng trong C#
- Tác giả: www.voer.edu.vn
- Đánh giá: 5 ⭐ ( 3543 lượt đánh giá )
- Khớp với kết quả tìm kiếm: Giới thiệu về lớp và đối tượng trong C# (giáo trình – tài liệu – học liệu từ VOER)
Lập trình hướng đối tượng (OOP) trong C#
- Tác giả: comdy.vn
- Đánh giá: 4 ⭐ ( 1853 lượt đánh giá )
- Khớp với kết quả tìm kiếm: Lập trình hướng đối tượng (OOP) trong C# là gì? 5 khái niệm và 4 tính chất quan trọng của lập trình hướng đối tượng là gì?
Constructor (hàm tạo/hàm dựng) trong C#, khởi tạo object
- Tác giả: tuhocict.com
- Đánh giá: 5 ⭐ ( 6564 lượt đánh giá )
- Khớp với kết quả tìm kiếm: Bài học này sẽ hướng dẫn bạn cách viết phương thức constructor (hàm tạo, hàm dựng) khi xây dựng class C# và các cách khởi tạo đối tượng cho class trong C#.
Lập trình hướng đối tượng trong C++
- Tác giả: www.elib.vn
- Đánh giá: 4 ⭐ ( 7007 lượt đánh giá )
- Khớp với kết quả tìm kiếm:
[C/C++] – Bài 14: Lập trình hướng đối tượng trong C++ (OOP)
- Tác giả: www.tbit.vn
- Đánh giá: 4 ⭐ ( 6905 lượt đánh giá )
- Khớp với kết quả tìm kiếm: * TÓM TẮT LÝ THUYẾT
1. Giới thiêu lập trình hướng đối tượng (OOP) với C++
– C++ là ngôn ngữ “lai” giữa lập trình Cấu trúc và Lập trình hướng đối…
Chi tiết bài học Lớp và đối tượng trong C++
- Tác giả: vimentor.com
- Đánh giá: 4 ⭐ ( 6946 lượt đánh giá )
- Khớp với kết quả tìm kiếm: Vimentor chi tiết bài học Lớp và đối tượng trong C++
Xem thêm các bài viết khác thuộc chuyên mục: Kiến thức lập trình