首页 > 解决方案 > 用于输入流读取的类模板函数 - C++

问题描述

我有点卡在我目前的项目上。我在一个类中创建了一个方法,该方法从文件中读取输入,并将其发送到 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++classtemplatesmethodsdynamic

解决方案


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

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

这是一些您可以充实的伪代码:

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模板违反了三/五规则;您定义了自定义析构函数,但未实现复制构造函数、复制赋值运算符、移动构造函数或移动赋值运算符。如果您对 a 进行按值复制,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:
    // ...
};

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


推荐阅读