【问题标题】:Class template function for input stream reading - C++用于输入流读取的类模板函数 - C++
【发布时间】:2020-08-15 14:51:07
【问题描述】:

我对当前的项目有点卡住了。我在一个类中创建了一个方法,该方法从文件中读取输入,并将其发送到一个 Result 对象(类)数组。当我这样做时,它使用结果类输入流方法以我想要的方式读取输入。现在我有一个名为 Vector 的自定义类模板,用于动态数组,其中 Result 是我的 Vector。我需要如何更改输入语法以及 Vector 中需要哪种方法?我用于读取结果对象数组的方法是这样的:

void Registration::SetSemester(unsigned semester1){
   semester = semester1;
}

void Registration::readFile(istream &input){
    long studentid1;
    unsigned semester1;

    input >> studentid1 >> semester1 >> count;

    SetStudentID(studentid1);
    SetSemester(semester1);

    for(unsigned i = 0; i < count; i++){
        input >> results[i];
    }
}

这是我的 Vector.h:

#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

template <class T>
class Vector
{
    public:
        Vector(int size = 10);
        ~Vector();

        void initialize(unsigned from = 0);
        void expand();
        void add(const T &obj);
        int size() const{return this->nrofel;}

        T& operator[](const int index);
        const T& operator[](const int index) const;

    private:
        T **data;
        unsigned capacity;
        unsigned nrofel;
};

template <class T>
Vector<T>::Vector(int size){
    this->capacity = size;
    this->nrofel = 0;
    this->data = new T*[this->capacity];

    this->initialize();
}

template <class T>
T& Vector<T>::operator[](int index){
    if(index < 0 || index > this->nrofel){
        throw("Out of bounds");
    }
    return *this->data[index];
}

template <class T>
const T& Vector<T>::operator[](int index) const{
    if(index < 0 || index > this->nrofel){
        throw("Out of bounds");
    }
    return *this->data[index];
}

template <class T>
void Vector<T>::initialize(unsigned from){
    for(size_t i = from; i < this->capacity; i++){
        this->data[i] = nullptr;
    }
}

template <class T>
Vector<T>::~Vector(){
    for(size_t i = 0; i < capacity; i++){
        delete this->data[i];
    }
    delete[]this->data;
}

template <class T>
void Vector<T>::expand(){
    this->capacity *= 2;
    T** tempData = new T*[this->capacity];
    for(size_t i = 0; i < this->nrofel; i++){
        tempData[i] = new T(*this->data[i]);
    }

    for(size_t i = 0; i < this->nrofel; i++){
       delete this->data[i];
    }

    delete[] data;
    this->data = tempData;
    this->initialize(this->nrofel);
}

template <class T>
void Vector<T>::add(const T &obj){
    if(this->nrofel >= this->capacity){
        this->expand();
    }
    this->data[this->nrofel++] = new T(obj);
}

我的 add 方法处理对象和几乎任何值,但是如何使该方法可用于从文件输入到数组中?

【问题讨论】:

    标签: c++ class templates methods dynamic


    【解决方案1】:

    为此,您需要为您的向量类型定义某种类型的序列化格式,并且您还需要依赖包含的类型来了解如何对其自身进行序列化和反序列化。

    序列化和反序列化都可以作为运算符实现,它们甚至不需要成为你的向量的朋友,因为它们可以针对公共接口工作。

    这里有一些你可以充实的伪代码:

    template <typename T>
    std::ostream & operator<<(std::ostream & stream, Vector<T> const & vec) {
        // Possibly write length information using vec.size()
        if (stream << vec.size()) {
            for (int i = 0; i < vec.size(); ++i) {
                // Possibly frame the data; regardless, write out each element using:
                if (!(stream << vec[i])) { break; }
            }
        }
    
        return stream;
    }
    
    template <typename T>
    std::istream & operator>>(std::istream & stream, Vector<T> & vec) {
        // Possibly read length information...
        int size;
        if (stream >> size) {
            while (size--) {
                // Possibly read framing.
                T value;
                if (!(stream >> value)) { break; }
                vec.add(value);
            }
        }
    
        return stream;
    }
    

    这显然不是一个完整的实现。您可能希望以某种方式为每个元素设置框架,以便了解每个元素的开始和结束位置。

    T 需要实现流式操作符才能编译。


    旁注:您的Vector 模板违反了rule of three/five;您定义了自定义析构函数,但未实现复制构造函数、复制赋值运算符、移动构造函数或移动赋值运算符。如果您对 Vector 进行值复制,则在使用另一个对象时,复制源或目标的破坏将导致未定义的行为。

    假设使用 C++11 编译器,最简单的解决方法是删除这些成员,这样编译器就不会生成不正确的版本:

    template <class T>
    class Vector
    {
    public:
        Vector(Vector const &) = delete;
        Vector(Vector &&) = delete;
    
        Vector & operator=(Vector const &) = delete;
        Vector & operator=(Vector &&) = delete;
    
        // ...
    };
    

    在旧版本的 C++ 中,将成员声明为私有但不提供实现。这将防止从类外部或其朋友进行复制,并且如果特权代码尝试进行复制,则会导致链接时错误:

    template <class T>
    class Vector
    {
    private:
        // Don't implement any of these!
        Vector(Vector const &);
        Vector(Vector &&);
    
        Vector & operator=(Vector const &);
        Vector & operator=(Vector &&);
    
    public:
        // ...
    };
    

    当然,如果可能,您应该实现这些,以便您的类型可以被正确复制/移动。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-04
      • 1970-01-01
      • 1970-01-01
      • 2010-12-27
      • 1970-01-01
      • 2022-01-11
      • 2018-03-05
      • 2013-06-19
      相关资源
      最近更新 更多