Gọi hàm thành viên c ++ từ c

chỉ cần thực hiện cuộc gọi đơn giản như dưới đây. lớp abc{ thành viên_func1(); . thành viên_func1(){ //. this->member_func2();// chỉ thực hiện cuộc gọi đơn giản //. }

Để hoàn thành cái đầu tiên, chúng ta sẽ cần một tài liệu tham khảo chung. Thực sự không có cách nào rõ ràng để cho C biết chính xác độ lớn của một đối tượng nhất định. Do đó, tài liệu tham khảo tốt nhất là một con trỏ tới lớp đó có thể được giữ và chuyển bởi mã C

Mã C với chức năng chính

1
2
3
4
5
6
7
8
9
10
11
12
#include 
#include "foo.h"

int main(const int argc, const char **argv)
{
   
   void *temp_foo = getFoo(5);

   printString(temp_foo);

   return( EXIT_SUCCESS );
}

Trong đoạn mã trên, bạn sẽ thấy rằng ở dòng 4, phương thức getFoo(5) trả về một con trỏ trống có tên là temp_foo. Đây là con trỏ tới lớp Foo của chúng ta mà chúng ta sẽ định nghĩa tiếp theo

Lớp Foo được định nghĩa trong tệp tiêu đề của chính nó. Điều này được thực hiện vì một số lý do, thứ nhất, nó giữ cho các chỉ thị của trình biên dịch trước đơn giản hơn và thứ hai, nó giúp đảm bảo các hàm truy cập cho C được xác định chính xác cho mọi hàm C++. Có khá nhiều thứ đang diễn ra ở đây, vì vậy hãy xem mã bên dưới và tất cả chúng ta sẽ giải thích

Tệp tiêu đề mục đích kép C ++ và C

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
 * gotta use stdint so we can use the same type in C++/C
 * could make the example a bit more complicated with some
 * #defines to fix but it's simpler this way.
 */
#include 


#ifdef __cplusplus

#include 

class Foo
{
public:
   Foo( int32_t a );
   ~Foo();
   std::string toString();
private:
   int32_t k;
};

#endif

#ifdef __cplusplus
extern "C" 
{
#endif

void*  getFoo( int32_t a );
void   destroyFoo( void *foo );
void   printString( void *foo );

#ifdef __cplusplus
}
#endif

Điều đầu tiên bạn sẽ thấy khác thường là câu lệnh __cplusplus ifdef. Điều này được xác định nếu tiêu đề này đang được xử lý bởi trình biên dịch c ++. Nếu bạn làm theo mã đến cuối if statemetn đầu tiên ở dòng 15, bạn sẽ thấy nó chỉ bao gồm định nghĩa lớp. Đó là bởi vì các lớp không được công nhận trong C++.
Khi tiêu đề này được trình biên dịch C xử lý, phần khai báo của lớp Foo và tất cả các hàm của nó sẽ biến mất hoàn toàn. Điều tiếp theo bạn sẽ nhận thấy là dòng 17. Nó có cùng lệnh như dòng 4, tuy nhiên lần này chúng ta sử dụng nó để chèn dòng bên ngoài “C” xung quanh các hàm được khai báo trên các dòng 20,21,22 kết thúc bằng cùng một khai báo với dấu ngoặc nhọn ở dòng 24. Điều này đảm bảo rằng khi tệp tiêu đề này và phần triển khai của nó được biên dịch thành một tệp đối tượng mà chúng không bị xáo trộn, nghĩa là chúng có thể được nhận dạng bởi tệp đối tượng do trình biên dịch C tạo ra. Bây giờ, nếu chúng ta loại bỏ mọi thứ chỉ được biên dịch bằng trình biên dịch C++ (mọi thứ được bao quanh bởi __cplusplus), chúng ta sẽ thấy rằng thứ duy nhất sẽ được biên dịch bởi trình biên dịch C khi chúng ta đưa vào tiêu đề này là các hàm ở 20, 21 và .

Tôi đã đề cập đến các chức năng của trình truy cập khá nhiều. Các hàm truy cập là một cách để chuyển đổi tham chiếu mà chúng ta đã chuyển đến C (con trỏ void) trở lại thành thứ gì đó mà C++ có thể sử dụng được và thực hiện điều gì đó với nó. Chúng ta sẽ thấy nhiều hơn về điều này tiếp theo

Triển khai C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include 
#include 
#include 
#include 

#include "foo.h"

Foo::Foo( int32_t a )
{
   k = a << 1;
}

Foo::~Foo()
{
   /* don't really need to do anything here */
   /* k = 0 only for example purposes       */
   k = 0;
}

std::string 
Foo::toString()
{
   std::ostringstream os;
   os << "Foo is currently: " << this->k << std::endl;
   return( os.str() );
}

void* 
getFoo( int32_t a )
{
   Foo *out( new Foo(a) );
   return( reinterpret_cast< void* >( out ) );
}

void 
destroyFoo( void* foo )
{
   delete( reinterpret_cast< Foo* >( foo ) );
}


void 
printString( void *foo )
{
   std::string s = reinterpret_cast< Foo* >( foo )->toString();
   std::cout << s;
}

Trong đoạn mã trên ở dòng 6, chúng ta thấy rằng tiêu đề của chúng ta, foo. h, được bao gồm. Tại các dòng 12 đến 18, chúng tôi đã định nghĩa tất cả các phương thức lớp của chúng tôi. Tại dòng 24 là nơi các chức năng C của chúng tôi bắt đầu. Có một vài hạn chế phải được đặt trên các chức năng này

  • Họ chỉ phải sử dụng các loại có sẵn cho C, i. e. C không có khái niệm về lớp
  • Thông thường, không nên cố gắng sử dụng một cấu trúc có cùng tên với lớp làm tham số

Cùng với đó, ý tưởng cơ bản là tạo một trình bao bọc cho từng hàm C++ mà chúng tôi muốn gọi từ C. Điêu nay bao gôm. hàm tạo, hàm hủy và bất kỳ phương thức nào chúng tôi muốn gọi trong tệp đối tượng được biên dịch C++. Điều cuối cùng bạn muốn làm là kết hợp tất cả lại với nhau bằng cách sử dụng Makefile và trình biên dịch C/C++ mà bạn chọn

Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
CC  ?= gcc
CXX ?= g++

CFLAGS = -O0 -g -Wall -pedantic 
CXXFLAGS = -O0 -g -Wall -pedantic

OBJ	= main foo
OBJS  = $(addsuffix .o,$(OBJ))
all:
	make compile

compile:
	make $(OBJS)
	make fooexe

fooexe: $(OBJS) 
	$(CXX) -o fooexe $(OBJS)

main.o: main.c
	$(CC) $(CFLAGS) -c -o main.o main.c

foo.o: foo.cpp
	$(CXX) $(CXXFLAGS) -c -o foo.o foo.cpp

clean:
	rm -rf $(OBJS) fooexe *.dSYM

Makefile ở trên hơi lạ nếu bạn chưa bao giờ biên dịch mọi thứ trước rồi liên kết tất cả lại với nhau. Nhìn vào dòng 9, chúng ta thấy rằng quy tắc tất cả các cuộc gọi thực hiện biên dịch. Tại dòng 12, chúng ta thấy lệnh gọi make compile make $(OBJS) tại thời điểm này lưu trữ chính. o và foo. o. Các quy tắc cho từng dòng ở dòng 19 và 22 tương ứng cho thấy rằng chúng được biên dịch bằng trình biên dịch C và C++ và mỗi quy tắc đều có cờ -c có nghĩa là chỉ biên dịch, không liên kết. Quy tắc cho fooexe được gọi ở dòng 14 là quy tắc thực sự thực thi liên kết của từng tệp đối tượng thành một tệp đối tượng thực thi fooexe

Tôi có thể gọi C++ từ C không?

Truy cập Mã C++ từ Nguồn C bên trong . Một hàm được khai báo là có liên kết C có thể sử dụng tất cả các tính năng của C++, nhưng các tham số và kiểu trả về của nó phải được truy cập từ C nếu bạn muốn gọi nó từ mã C. If you declare a C++ function to have C linkage, it can be called from a function compiled by the C compiler. A function declared to have C linkage can use all the features of C++, but its parameters and return type must be accessible from C if you want to call it from C code.

Làm cách nào để gọi một hàm thành viên từ một hàm thành viên khác C++?

chỉ cần thực hiện cuộc gọi đơn giản như bên dưới. lớp abc{ member_func1(); . thành viên_func1(){ //.

Cú pháp chính xác để gọi hàm thành viên là gì?

Giải thích. Các hàm thành viên chỉ có thể được gọi bằng cách sử dụng toán tử dấu chấm hoặc toán tử mũi tên . Nhưng các thành viên tĩnh có thể được gọi bằng cách sử dụng trực tiếp tên lớp theo sau là toán tử phân giải phạm vi và tên hàm thành viên tĩnh. Điều này rất hữu ích khi bạn không có bất kỳ đối tượng nào để gọi thành viên.

Thành viên có thể là một hàm C++ không?

Hàm thành viên của một lớp là một hàm có định nghĩa hoặc nguyên mẫu của nó trong định nghĩa lớp giống như bất kỳ biến nào khác . Hàm thành viên trong C++ hoạt động trên bất kỳ đối tượng nào của lớp mà nó là thành viên và có quyền truy cập vào tất cả các thành viên của lớp đối với đối tượng đó.