ah
#include "logic.h"
...
class A
{
friend ostream& operator<<(ostream&, A&);
...
};
logic.cpp
#include "a.h"
...
ostream& logic::operator<<(ostream& os, A& a)
{
...
}
...
Ketika saya mengkompilasi, dikatakan:
std :: ostream & logic :: operator << (std :: ostream &, A &) 'harus mengambil tepat satu argumen.
Apa masalahnya?
c++
operator-overloading
iostream
Sebagai As
sumber
sumber
Fungsi teman bukanlah fungsi anggota, jadi masalahnya adalah Anda menyatakan
operator<<
sebagai teman dariA
:friend ostream& operator<<(ostream&, A&);
kemudian cobalah untuk mendefinisikannya sebagai fungsi anggota kelas
logic
ostream& logic::operator<<(ostream& os, A& a) ^^^^^^^
Apakah Anda bingung tentang apakah
logic
itu kelas atau namespace?Kesalahannya adalah karena Anda mencoba untuk mendefinisikan anggota yang
operator<<
mengambil dua argumen, yang berarti dibutuhkan tiga argumen termasukthis
parameter implisit . Operator hanya bisa mengambil dua argumen, sehingga saat Anda menulisa << b
dua argumen tersebut adalaha
danb
.Anda ingin mendefinisikan
ostream& operator<<(ostream&, const A&)
sebagai fungsi non- anggota , jelas bukan sebagai anggotalogic
karena tidak ada hubungannya dengan kelas itu!std::ostream& operator<<(std::ostream& os, const A& a) { return os << a.number; }
sumber
Saya mengalami masalah ini dengan kelas template. Berikut solusi yang lebih umum yang harus saya gunakan:
template class <T> class myClass { int myField; // Helper function accessing my fields void toString(std::ostream&) const; // Friend means operator<< can use private variables // It needs to be declared as a template, but T is taken template <class U> friend std::ostream& operator<<(std::ostream&, const myClass<U> &); } // Operator is a non-member and global, so it's not myClass<U>::operator<<() // Because of how C++ implements templates the function must be // fully declared in the header for the linker to resolve it :( template <class U> std::ostream& operator<<(std::ostream& os, const myClass<U> & obj) { obj.toString(os); return os; }
Sekarang: * Fungsi toString () saya tidak bisa sebaris jika akan disimpan di cpp. * Anda terjebak dengan beberapa kode di header, saya tidak bisa menyingkirkannya. * Operator akan memanggil metode toString (), itu tidak sebaris.
Badan operator << dapat dideklarasikan di klausa teman atau di luar kelas. Kedua opsi itu jelek. :(
Mungkin saya salah paham atau melewatkan sesuatu, tetapi hanya menyatakan terus template operator tidak ditautkan di gcc.
Ini juga berfungsi:
template class <T> class myClass { int myField; // Helper function accessing my fields void toString(std::ostream&) const; // For some reason this requires using T, and not U as above friend std::ostream& operator<<(std::ostream&, const myClass<T> &) { obj.toString(os); return os; } }
Saya pikir Anda juga dapat menghindari masalah template yang memaksa deklarasi di header, jika Anda menggunakan kelas induk yang tidak memiliki template untuk mengimplementasikan operator <<, dan menggunakan metode toString () virtual.
sumber
Jika Anda mendefinisikan
operator<<
sebagai fungsi anggota, itu akan memiliki sintaks terdekomposisi yang berbeda dibandingkan jika Anda menggunakan non-anggotaoperator<<
. Seorang non-anggotaoperator<<
adalah operator biner, di mana anggotaoperator<<
adalah operator unary.// Declarations struct MyObj; std::ostream& operator<<(std::ostream& os, const MyObj& myObj); struct MyObj { // This is a member unary-operator, hence one argument MyObj& operator<<(std::ostream& os) { os << *this; return *this; } int value = 8; }; // This is a non-member binary-operator, 2 arguments std::ostream& operator<<(std::ostream& os, const MyObj& myObj) { return os << myObj.value; }
Jadi .... bagaimana Anda benar-benar memanggil mereka? Operator itu aneh dalam beberapa hal, saya akan menantang Anda untuk menulis
operator<<(...)
sintaks di kepala Anda untuk membuat semuanya masuk akal.MyObj mo; // Calling the unary operator mo << std::cout; // which decomposes to... mo.operator<<(std::cout);
Atau Anda dapat mencoba menelepon operator biner non-anggota:
MyObj mo; // Calling the binary operator std::cout << mo; // which decomposes to... operator<<(std::cout, mo);
Anda tidak memiliki kewajiban untuk membuat operator ini berperilaku secara intuitif saat Anda menjadikannya sebagai fungsi anggota, Anda dapat menentukan
operator<<(int)
shift kiri beberapa variabel anggota jika Anda mau, memahami bahwa orang mungkin sedikit lengah, tidak peduli berapa banyak komentar Anda. menulis.Hampir terakhir, mungkin ada saat di mana kedua dekomposisi untuk panggilan operator valid, Anda mungkin mendapat masalah di sini dan kami akan menunda percakapan itu.
Terakhir, perhatikan betapa anehnya menulis operator anggota unary yang seharusnya terlihat seperti operator biner (karena Anda dapat menjadikan operator anggota virtual ..... juga berusaha untuk tidak berpindah dan menjalankan jalur ini .... )
struct MyObj { // Note that we now return the ostream std::ostream& operator<<(std::ostream& os) { os << *this; return os; } int value = 8; };
Sintaks ini akan mengganggu banyak pembuat kode sekarang ....
MyObj mo; mo << std::cout << "Words words words"; // this decomposes to... mo.operator<<(std::cout) << "Words words words"; // ... or even further ... operator<<(mo.operator<<(std::cout), "Words words words");
Perhatikan bagaimana
cout
argumen kedua dalam rantai di sini .... ganjil kan?sumber