迭代器和重载<<运算符
Iterators and Overloading << Operator
我已经截断了这篇文章。为了方便阅读,最初的帖子已经删除。相关的部分和问题仍然存在。
更新strong>
我被要求发布的错误是:
[mehoggan@desktop qsort]$ g++ -o qsort -Wall main.cpp
/tmp/ccuAUzlh.o: In function `Sorters::QuickSorter<float>::test_and_sort(float*, int)':
main.cpp:(.text._ZN7Sorters11QuickSorterIfE13test_and_sortEPfi[Sorters::QuickSorter<float>::test_and_sort(float*, int)]+0x61): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& Sorters::operator<< <float>(std::basic_ostream<char, std::char_traits<char> >&, Sorters::Sorter<float>&)'
collect2: ld returned 1 exit status
[mehoggan@desktop qsort]$
,使用下面的代码:
#ifndef SORTERS_H_
#define SORTERS_H_
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cmath>
#include <ctime>
#include <assert.h>
using std::vector;
using std::cin;
using std::cout;
using std::endl;
using std::ostream_iterator;
using std::istream_iterator;
using std::next_permutation;
using std::back_inserter;
using std::ostream;
namespace Sorters {
template<typename T>
class Sorter {
public:
Sorter( ) { };
virtual ~Sorter( ) { };
virtual void test_and_sort( T *data, int size )=0;
protected:
virtual void sort( typename vector<T>::iterator left, typename vector<T>::iterator right )=0;
vector<T> m_data;
};
template<typename T>
class QuickSorter : public Sorter<T> {
public:
QuickSorter( ) { };
virtual ~QuickSorter( ) { };
virtual void test_and_sort( T *data, int size );
private:
virtual void sort( typename std::vector<T>::iterator left, typename std::vector<T>::iterator right );
template<typename S> friend ostream& operator<< ( ostream &stream, Sorter<S> &sorter );
};
}
template<typename T>
void Sorters::QuickSorter<T>::sort( typename vector<T>::iterator left, typename vector<T>::iterator right ) {
}
template<typename T>
void Sorters::QuickSorter<T>::test_and_sort( T *data, int size ) {
for( int i=0;i<size;i++ ) {
vector<T> perm( &data[0], &data[i+1] );
do {
cout << (*this) << endl;
copy( perm.begin( ),perm.end( ),back_inserter( m_data ) );
this->sort( m_data.begin( ), m_data.end( ) );
} while( next_permutation( perm.begin( ), perm.end( ) ) );
m_data.clear( );
}
}
template<typename S> ostream& operator<< ( ostream &stream, Sorters::Sorter<S> &sorter ) {
copy( sorter->m_data.begin( ),sorter->m_data.end( ), ostream_iterator<S>( stream," " ) );
return stream;
}
#endif
更新strong>我写了一个较小的例子,所以我知道我的概念是有效的,当我使用多态性和朋友函数时,它会变得混乱。
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
class Sample {
public:
Sample( ) { };
Sample( float *data, int size ) {
copy(&data[0],&data[size],back_inserter( m_data ) );
};
~Sample( ) { };
private:
vector<float> m_data;
friend ostream& operator<< ( ostream &stream, Sample &s ) {
copy( s.m_data.begin( ), s.m_data.end( ), ostream_iterator<float>( stream, " " ) );
return stream;
}
};
int main( int argc, char *argv[] ) {
float data[ ] = {1,2,3,4,5};
Sample s(data,5);
cout << s;
}
<
解决方案/strong>
Now to write the actual algorithm. I noticed though if I move m_data up to the parrent class I get compiler errors saying that m_data cannot be found. I guess that just means Insertion Sort, Radix Sort, Stooge Sort, ... will all have there own container.
#ifndef SORTERS_H_
#define SORTERS_H_
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cmath>
#include <ctime>
#include <assert.h>
using std::vector;
using std::cin;
using std::cout;
using std::endl;
using std::ostream_iterator;
using std::istream_iterator;
using std::next_permutation;
using std::back_inserter;
using std::ostream;
namespace Sorters {
template<typename T>
class Sorter {
public:
Sorter( ) { };
virtual ~Sorter( ) { };
virtual void test_and_sort( T *data, int size )=0;
protected:
virtual void sort( typename vector<T>::iterator left, typename vector<T>::iterator right )=0;
};
template<typename T>
class QuickSorter : public Sorter<T> {
public:
QuickSorter( ) { };
virtual ~QuickSorter( ) { };
virtual void test_and_sort( T *data, int size );
private:
vector<T> m_data;
virtual void sort( typename std::vector<T>::iterator left, typename std::vector<T>::iterator right );
friend ostream& operator<< ( ostream &stream, const QuickSorter &sorter ) {
copy( sorter.m_data.begin( ),sorter.m_data.end( ),ostream_iterator<T>( stream," " ) );
return stream;
}
};
}
template<typename T>
void Sorters::QuickSorter<T>::sort( typename vector<T>::iterator left, typename vector<T>::iterator right ) {
}
template<typename T>
void Sorters::QuickSorter<T>::test_and_sort( T *data, int size ) {
for( int i=0;i<size;i++ ) {
vector<T> perm( &data[0], &data[i+1] );
do {
copy( perm.begin( ),perm.end( ),back_inserter( m_data ) );
cout << (*this) << endl;
this->sort( m_data.begin( ), m_data.end( ) );
m_data.clear( );
} while( next_permutation( perm.begin( ), perm.end( ) ) );
}
}
#endif
首先,您要通过打印this
来打印地址。您需要打印为,
cout << *this << endl;
在您提到的评论中,您会得到错误。这是因为operator << ()
中的以下行:
vector<S> copy = sorter.m_data; // <--- where is 'm_data' ??
sorter
为class Sorter<S>
型,其中不存在m_data
。
要解决这个问题,要么将m_data
从QuickSorter
移动到Sorter
,要么用QuickSorter<S>&
重载operator <<
。
在Sorters
命名空间之外定义operator <<
重载。这是一个错误:您需要在与类相同的命名空间中定义它(首先,这是您使用friend
声明声明它的地方;其次,这是参数依赖循环查找重载的地方(当您稍后使用它时)。
为什么显示的代码是这样的,在注释中解释了:cout << this
打印一个指针,结果输出一个地址。你的operator <<
重载需要一个对象的引用,而不是一个指针,所以它不会被使用。正如你所说,解决这个问题的方法是使用cout << *this
。
当我进行更改时,我以链接器错误告终。在模板和名称空间之间的某个地方,有些东西混淆了,我不清楚是什么。所以我采用了简单的解决方案:在类中定义函数。
代替
template<typename T>
struct QuickSorter {
template<typename T> friend ostream& operator <<(ostream&, QuickSorter<T>&);
}
template<typename T>
ostream& operator <<(ostream&, QuickSorter<T>&) { }
我做
template<typename T>
struct QuickSorter {
friend ostream& operator <<(ostream&, QuickSorter&) { }
};
现在,您不必担心模板参数是否正确。模板化函数无论如何都必须声明为内联的,因此您不妨这样做并完成它。请注意,您也没有将operator <<
声明为模板本身…你只对给一个过载的人提供友谊感兴趣,因为这个类恰好使用了特定的T
。
然后,您得到通知,该函数访问m_data
成员,该成员在Sorter<T>
中不存在。这很简单:Sorter<T>
没有这个成员;QuickSorter<T>
。因此,将函数的第二个形参更改为QuickSorter<T>&
,以便编译器可以找到特定的成员。这一变化也反映在上面。
我要做的最后一件事是使操作符重载接受const QuickSorter<T>&
而不是非const。它不以任何方式修改对象,所以没有理由不这样做。
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 如何显式调用运算符<<
- 为什么COUT在朋友函数中不起作用,该功能超载了操作员&lt;&lt;这是一个iStream运算符
- C++运算符<<调用::ostream而不是std::osttream
- BOOST ::变体无法解决运算符&lt;&lt;对于STD :: Ostream
- 过载输出<<用于类的运算符,以打印其中的元组
- C++ostream:没有运算符匹配<<&应在'&'代币
- 重载运算符<<:此运算符函数的参数太多
- C++继承运算符<<
- 重载运算符<<用于模板类.即使使用好友关键字也无法获得私人会员
- 如何过载<<用于YAML::Emitter的运算符,以序列化包含另一个自定义类的向量的自定义类
- 为什么字符串流运算符<<擦除原始值
- 关于使用运算符<<为新手提供C++中的模板
- 我已经完成了<<运算符重载,但它'It’不起作用
- 重载运算符<<输出地址而不是数据成员
- 错误:没有匹配'运算符<<"在'std::cout
- 重载运算符<<用于ostream语法
- 当运算符<存在时,为什么要定义 LT?
- log4cxx访问异常,使用<<运算符和宏
- 重载<<运算符错误C2804:二进制'运算符<<'参数太多