Yang mana dari jawaban ini mengenai fungsi yang tidak benar?

17

Jadi, sementara saya telah melakukan beberapa kompilasi panjang saya memutuskan untuk mengambil tes umum C ++ di ODesk dan menemukan pertanyaan ini.

Pertanyaan ini

Jika saya tidak salah, dengan kata-kata (atau kekurangannya) semua ini bisa benar.

Sebuah.

int Foo() { }
int Foo(int bar) { }

b. Yah, return void;semantik akan salah tetapi fungsi jelas dapat memiliki voidtipe kembali.

void Foo() { }

c. Ini adalah definisi fungsi sebaris, ya.

d. Tanpa banyak detail tentang penempatan elemen-elemen berikut,

typedef void (*Func)(int);

Func functions[2];

void Foo(int bar) { }
void Bar(int foo) { }

functions[0] = &Foo;
functions[1] = &Bar;

Selanjutnya, Anda selalu bisa melakukan ini menggunakan lambdas dan functors .

e.

void Foo(int& bar)
{
    ++bar;
}

int foobar = 5;
Foo(foobar);

f.

int bar = 5;

int& GetBar()
{
    return bar;
}

GetBar() = 6;

g.

int bar = 5;

int* GetBar()
{
    return &bar;
}

(*GetBar()) = 5;

Saya gagal melihat di mana pertanyaan ini memiliki jawaban yang benar-benar salah . Apakah saya melewatkan sesuatu?

Tak perlu dikatakan saya kehabisan waktu dan gagal semuanya. Saya kira saya seorang programmer C ++ yang buruk. :(

Qix
sumber
18
Datang ke sini untuk berteriak pada beberapa anak yang menempelkan PR, terkejut.
SomeKittens
Sebenarnya tidak semua bahasa mengharuskan fungsi inline diperluas. "inline" adalah petunjuk kompiler daripada perintah dalam Delphi, dan C, C ++ memiliki pengecualian . Jadi "c" juga bisa salah. Mungkin lebih menghibur untuk menulis jawaban yang menunjukkan bagaimana setiap pernyataan bisa salah.
Móż
1
@ Ӎσᶎ Kalau saja ada kotak teks. Saya ingin kembali dan menekan "Laporkan masalah dengan pertanyaan ini".
Qix
5
Itu bukan array fungsi. Itu adalah array fungsi pointer.
user253751
@immibis Benar, tetapi pertanyaannya tidak terlalu jelas (setidaknya bagi saya itu tidak).
Qix

Jawaban:

21

Seluruh pertanyaan ini cerdik. Pernyataan pertanyaan menyiratkan kemungkinan pilihan ganda, sedangkan tombol radio menunjukkan pilihan tunggal.

Selain itu, b cukup mencurigakan, karena fungsi void tidak mengembalikan apa pun.

D juga dipertanyakan, sejauh yang saya tahu, Anda tidak dapat memiliki berbagai fungsi. Tentu, Anda dapat memiliki berbagai fungsi pointer, tapi itu bukan hal yang persis sama.

Apa namanya
sumber
Baik; D seperti menanyakan apakah Anda dapat memanggil int. Tentu, jika Anda melemparkannya ke sebuah pointer dan pointer itu merujuk ke suatu fungsi ...
Qix
1
Saya berani bertaruh D adalah jawaban yang mereka tuju, tapi ya, pertanyaannya buruk.
Gort the Robot
Meskipun voidfungsi tidak mengembalikan nilai apa pun , mereka tetap mengembalikan jenisnya void . Jadi saya katakan B benar.
Thomas Eding
@ ThomasEding Itu masih kata-kata yang sangat buruk di pihak mereka. Anda tidak melakukannya return void;, tetapi sebaliknya return;.
Qix
10

Jawaban c) juga bisa dibilang salah.

"Fungsi sebaris diperluas selama waktu kompilasi untuk menghindari overhead doa."

Pertama, kompiler C ++ diizinkan untuk mengabaikan inlinepetunjuk dengan tidak memperluas fungsi sama sekali.

Kedua, "alasan" yang dinyatakan untuk melakukan ekspansi adalah penyederhanaan yang berlebihan. Faktanya, alasan sebenarnya untuk melakukan ekspansi (atau tidak) sepenuhnya ada di tangan penulis kompiler.

Stephen C
sumber
Anda benar, tetapi saya berpikir tentang hal itu dalam arti 'oke, kompiler telah menentukan bahwa ia memang ingin menyelaraskan fungsi' daripada inlinepetunjuknya.
Qix
Nah, kompiler tidak bisa sepenuhnya mengabaikan petunjuk itu. Setidaknya itu adalah efek yang diamanatkan, membuat pengecualian untuk ODR.
Deduplicator
@Dupuplikator - Ya itu bisa. "Tidak peduli bagaimana Anda menunjuk suatu fungsi sebagai inline, itu adalah permintaan bahwa kompiler diperbolehkan untuk mengabaikan: kompiler mungkin inline-memperluas beberapa, semua, atau tidak ada tempat di mana Anda memanggil fungsi yang ditunjuk sebagai inline." - source isocpp.org/wiki/faq/Inline-Functions
Stephen C
@StephenC: Permintaan untuk memperluas inline dapat diabaikan, ya. Saya hanya mengatakan bahwa pengecualian eksplisit untuk ODR tidak bisa.
Deduplicator
Saya melihat. Saya telah memperbarui kata-kata dari jawaban saya
Stephen C
7

c. Ini adalah definisi fungsi sebaris, ya.

Itu tidak sepenuhnya benar.
Terlepas dari namanya, kata kunci inlinetidak menjamin bahwa suatu fungsi akan digarisbawahi. Satu-satunya hal yang dapat Anda yakini adalah bahwa kompiler tidak akan mengeluh jika melihat definisi fungsi inline beberapa kali.

Jadi, sebenarnya, opsi C tidak benar, tetapi saya tidak berpikir itu adalah jawaban yang diharapkan oleh penulis kuis, karena ada jawaban yang bahkan lebih salah.

d. Tanpa banyak detail tentang penempatan elemen-elemen berikut,

typedef void (*Func)(int);

Func functions[2];

void Foo(int bar) { }
void Bar(int foo) { }

functions[0] = &Foo;
functions[1] = &Bar;

Lebih lanjut, Anda selalu bisa melakukan ini menggunakan lambdas dan functors.

Dalam contoh Anda, functionsadalah array pointer ke fungsi dan bukan array fungsi itu sendiri. Demikian pula, lambdas dan functors juga tidak benar-benar berfungsi. Mereka adalah kelas yang merespons operator fungsi-panggilan, tetapi itu tidak membuat mereka berfungsi di mata definisi bahasa C ++.

Fungsi dalam C ++ agak mirip warga negara kelas dua. Anda dapat mendefinisikan dan memanggil mereka, tetapi segera setelah Anda mencoba melakukan sesuatu yang lain dengan tipe fungsi (seperti membuat array dari mereka), Anda mendapatkan kesalahan atau mereka secara diam-diam mengubah diri mereka dalam sebuah pointer.

Bart van Ingen Schenau
sumber
Saya setuju dengan D bit, tetapi saya membaca csebagai fungsi yang telah ditandai positif untuk inlining, versus inlinekata kunci itu sendiri. Saya mengerti inlineadalah sebuah petunjuk.
Qix
4

Jika ada, itu harus b . Anda tidak bisa returnseorang void, tetapi Anda dapat mengembalikan null. Void pada deklarasi fungsi harus ada di sana untuk memberi tahu kompilator tentang kurangnya nilai yang dikembalikan.

Jenis Void

Dalam C dan C ++

Fungsi dengan tipe hasil batal berakhir dengan mencapai akhir fungsi atau dengan menjalankan pernyataan pengembalian tanpa nilai yang dikembalikan. Jenis void juga dapat muncul sebagai satu-satunya argumen prototipe fungsi untuk menunjukkan bahwa fungsi tidak memerlukan argumen. Perhatikan bahwa terlepas dari namanya, dalam semua situasi ini, tipe void berfungsi sebagai tipe unit, bukan sebagai tipe nol atau dasar, meskipun tidak seperti tipe unit nyata yang merupakan singleton, tipe void dikatakan terdiri dari kosong set nilai, dan bahasa tidak menyediakan cara apa pun untuk mendeklarasikan objek atau mewakili nilai dengan tipe batal.

Adam Zuckerman
sumber
2
-1: Meskipun voidfungsi tidak mengembalikan nilai apa pun , mereka tetap mengembalikan jenisnya void . Jadi saya katakan B benar.
Thomas Eding
Membatalkan pengembalian diizinkan dalam beberapa keadaan. Lihat di sini .
Josh Kelley