ข้อผิดพลาด typecast C ++ [ซ้ำกัน]

ความเป็นไปได้ที่ซ้ำกัน:
ตัวชี้โมฆะ: ความแตกต่างระหว่าง ซี และ ซี++

สวัสดี ฉันมีฟังก์ชั่นดังต่อไปนี้:

void task2(int a)
{
    printf("  Task 2 running..\n");
    sleep(2);
    printf("  Task 2 exiting..\n");
}

thpool_add_work(threadpool, (void*)task2, (void*)a);

int thpool_add_work(thpool_t* tp_p, void *(*function_p)(void*), void* arg_p)
{
    // some code here
}

โค้ดด้านบนทำงานได้ดีกับ C แต่ไม่สามารถคอมไพล์ใน C++ ได้ ฉันได้รับข้อผิดพลาดต่อไปนี้:

error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’
error:   initializing argument 2 of ‘int thpool_add_work(thpool_t*, void* (*)(void*), void*)’

ฉันไม่สามารถหาสาเหตุของข้อผิดพลาดนี้ได้ มีความคิดใดบ้างว่าทำไมข้อผิดพลาดนี้ถึงเกิดขึ้นเมื่อฉันเปลี่ยนนามสกุลไฟล์เป็น CPP และคอมไพล์


person webgenius    schedule 04.10.2012    source แหล่งที่มา
comment
คุณต้องโพสต์โค้ดเพิ่มเติม เช่น การประกาศฟังก์ชันและอ็อบเจ็กต์   -  person Konrad Rudolph    schedule 04.10.2012
comment
ไม่ใช่เพราะว่า void* สามารถแปลงเป็น C ได้โดยปริยาย แต่ไม่ใช่ใน C++ ใช่หรือไม่   -  person verdesmarald    schedule 04.10.2012
comment
ในภาษา C++ การแปลงตัวชี้ข้อมูล (เช่น void*) เป็นตัวชี้ฟังก์ชัน (เช่น void* (*)(void*)) ไม่ถูกกฎหมาย ไม่ว่าคอมไพเลอร์จำนวนมากจะยอมให้คุณทำสิ่งนี้ได้อย่างไร ฉันจะลบหรือปรับการแสดงของ task2 ที่คุณทำเมื่อคุณโทร thread_add_work ฉันยังจะลบ (void*) นักแสดงของ a ซึ่งดูเหมือนว่าจะไม่มีจุดประสงค์ด้วย การแคสต์มากเกินไปถือเป็นสัญญาณที่ไม่ดีเสมอไป เพียงแต่ซ่อนข้อผิดพลาดเอาไว้   -  person john    schedule 04.10.2012
comment
ภารกิจ 2 คืออะไร? มันเป็นฟังก์ชั่นหรือเปล่า?   -  person weima    schedule 04.10.2012
comment
เพิ่งอัปเดตเนื้อหาของงาน 2 ในคำถาม   -  person webgenius    schedule 04.10.2012


คำตอบ (2)


คุณต้องเปลี่ยนลายเซ็นของ task2 เพื่อให้ตรงกับประเภทของอาร์กิวเมนต์ thpool_add_work:

void* task2(void* a)

การเรียกที่สร้างเธรดจะกลายเป็น

thpool_add_work(threadpool, task2, &a);

สมมติว่า a คือ int

หากคุณต้องการใช้อาร์กิวเมนต์ task2 คุณสามารถดำเนินการต่อไปนี้:

int ia = *(int*)a;

อัปเดตเพื่อตอบความคิดเห็น OP

thpool_add_work คาดหวังฟังก์ชันที่มีอาร์กิวเมนต์ void* ด้วยเหตุผล ด้วยวิธีนี้ คุณสามารถส่งพารามิเตอร์ชนิดใดก็ได้ไปยังฟังก์ชันเธรด แม้ว่าจะเป็นประเภทที่ไม่ปลอดภัยก็ตาม

คุณส่งที่อยู่ของพารามิเตอร์ที่แปลงเป็น void* เป็นอาร์กิวเมนต์ที่ 3 ของ thpool_add_work หลังจากนั้น คุณส่งพอยน์เตอร์ไปที่ void กลับไปที่พอยน์เตอร์ตามประเภทพารามิเตอร์ที่คุณคาดหวัง และทำการอ้างอิงเพื่อรับค่าของพารามิเตอร์ ฉันยกตัวอย่างสำหรับ int a ข้างต้น แล้วตอนนี้มันจะมีลักษณะอย่างไรหากทศนิยม:

void* test3(void* a)
{
float fa = *(float*)a;
.....
return NULL;
}
person Andrey    schedule 04.10.2012
comment
Task2 จำเป็นต้องแปลงมันเป็น int และ Task3 จำเป็นต้องแปลง void* ให้เป็น float ฉันไม่แน่ใจว่าการเปลี่ยนพารามิเตอร์เป็น void* a จะช่วยได้อย่างไร คุณช่วยอธิบายรายละเอียดหน่อยได้ไหม? - person webgenius; 04.10.2012
comment
@webgenius: คำตอบได้รับการอัปเดตแล้ว - person Andrey; 04.10.2012

ลองสิ่งนี้

thpool_add_work(threadpool, (void* (*)(void*))task2, (void*)a);

C แปลง void* เป็นประเภทใดก็ได้โดยอัตโนมัติ แต่ C++ จะไม่แปลง

คุณสามารถปรับปรุงโค้ดด้วย typedef

typedef void* (*worker_func_t)(void*);

thpool_add_work(threadpool, (worker_func_t)task2, (void*)a);

int thpool_add_work(thpool_t* tp_p, worker_func_t function_p, void* arg_p)
{
    // some code here
}
person john    schedule 04.10.2012