【问题标题】:Iterators and Overloading << Operator迭代器和重载 << 运算符
【发布时间】:2011-10-18 19:08:09
【问题描述】:

我已经截断了这篇文章。为了方便阅读,最初的帖子已经消失了。相关部分和问题仍然存在。


更新

我被要求发布的错误是:

[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

更新 我写了一个较小的例子,所以我知道我的概念是有效的,但当我使用多态性和友元函数时,它只会被混淆。

#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;
}

解决方案

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

【问题讨论】:

  • 这是因为类方法 test_and_sort 中的语句 - cout &lt;&lt; this &lt;&lt; endl;。您只是在打印 this 指向的位置。注意地址位置在整个循环中是等效的。
  • 是的,你很快。我刚刚修改了我的问题。我尝试将其更改为 cout
  • 正是这就是为什么我会做我上面所做的,一旦我有了对象,通过一个朋友函数访问它的成员变量。

标签: c++ stl iterator operator-overloading


【解决方案1】:

首先通过打印this 打印地址。您需要打印为,

cout << *this << endl;

在您提到的 cmets 中,您遇到了错误。这是因为operator &lt;&lt; () 中的以下行:

vector<S> copy = sorter.m_data;  // <--- where is 'm_data' ??

sorterclass Sorter&lt;S&gt; 类型,里面没有 m_data

要解决此问题,请将 m_dataQuickSorter 移动到 Sorter 或使用 QuickSorter&lt;S&gt;&amp; 重载 operator &lt;&lt;

【讨论】:

  • 当我将 m_data 向上移动到 Sorter 或将类型切换到 QuickSorter 时,使用 cout this) ::test_and_sort(float, int)]+0x61): 未定义引用`std::basic_ostream >& Sorters::operator(std::basic_ostream >&, Sorters::Sorter&)' collect2: ld 返回 1 个退出状态跨度>
  • @Matthew 您可以在问题本身中发布错误。这似乎是一个链接器错误。我认为,您在这两个地方都没有对operator &lt;&lt;() 进行更改。我将编辑我的答案。
【解决方案2】:

您在 Sorters 命名空间之外定义了 operator &lt;&lt; 重载。这是一个错误:您需要在与类相同的命名空间中定义它(首先,这是您使用 friend 声明声明它的地方;其次,这是依赖于参数的循环正在寻找的地方用于以后使用时的重载)。

【讨论】:

    【解决方案3】:

    在 cmets 中解释了为什么所示代码的行为方式:cout &lt;&lt; this 打印一个指针,从而输出一个地址。您的 operator &lt;&lt; 重载需要对对象的引用,而不是指针,因此它不会被使用。正如你所说,解决方案是使用cout &lt;&lt; *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 &lt;&lt; 声明为模板本身...您只对给一个重载提供友谊感兴趣,因为该类恰好正在使用特定的 T

    然后,您会得知该函数访问了成员 m_data,而该成员在 Sorter&lt;T&gt; 中不存在。这很简单:Sorter&lt;T&gt; 没有该成员; QuickSorter&lt;T&gt; 确实如此。因此,将函数的第二个参数更改为QuickSorter&lt;T&gt;&amp;,以便编译器可以找到该特定成员。这种变化也反映在上面。

    我要做的最后一件事是让运算符重载接受const QuickSorter&lt;T&gt;&amp; 而不是非常量。它不会以任何方式修改对象,因此没有理由不这样做。

    【讨论】:

      猜你喜欢
      • 2013-09-07
      • 2016-02-03
      • 2020-06-14
      • 1970-01-01
      • 2011-12-07
      • 2017-02-22
      • 2012-03-12
      • 2022-01-10
      • 1970-01-01
      相关资源
      最近更新 更多