c++ - dynamic_cast 模板类 "invalid target type for dynamic_cast"

标签 c++ dynamic-cast

在模板类中,我尝试使用 dynamic_cast 从文件中读取的字符串进行转换,并希望能够使用 bad_cast 异常捕获失败的转换。但是,在编译时(将测试程序设置为 double 作为模板类,我得到 dynamic_cast 的这个错误:

datafilereader.cpp(20): error C2680: 'double *' : invalid target type for dynamic_cast

我试着把它写成 <T>而不是 <T*> (当我查看有关动态转换的其他问题时,后者似乎是常见的方式......),但实际上是相同的错误。

数据文件读取器.cpp

#include "DataFileReader.h"
#include <typeinfo>

template <typename T>
void DataFileReader<T>::openFiles() {
    dataFileStream.open(dataFileName);
    errorFileStream.open(errorFileName, ios::app);
    if (!(dataFileStream.is_open() && errorFileStream.is_open()))
            throw(runtime_error("Couldn't open at least one of the files."));
}

template <typename T>
bool DataFileReader<T>::readNextValue(T &aValue) {
    ios_base::iostate mask = ios::eofbit|ios::failbit|ios::badbit;
    dataFileStream.exceptions(mask);
    while (true) {
        string readValue;
        try {
            dataFileStream >> readValue;
            aValue = dynamic_cast<T*>(readValue);
            return true;
        }
        catch(bad_cast &bc) {
            errorFileStream << readValue << " - " << bc.what() << endl;
        }
        catch(ios_base::failure &eo) {
            if(dataFileStream.eof())
                return false;
        }
    }
}

数据文件读取器.h

#ifndef DataFileReader_H
#define DataFileReader_H

#include <string>
#include <iostream>
#include <fstream>

using namespace std;

template <typename T>
class DataFileReader {

    private:
        string dataFileName;
        string errorFileName;
        ifstream& dataFileStream;
        ofstream& errorFileStream;

    public: 
        DataFileReader(string aDataFileName, string aErrorFileName): dataFileName(aDataFileName), errorFileName(aErrorFileName), dataFileStream(*(new std::ifstream(""))), errorFileStream(*(new std::ofstream(""))) {};
        /* pre: A file named aDataFile contains values to read. */
        ~DataFileReader() {dataFileStream.close(); errorFileStream.close(); delete dataFileStream; delete errorFileStream;}
        /* post: Files are closed */
        void openFiles(); // throw (runtime_error);
        /* post: An input stream from the file named aDataFile and an output stream to the file named aErrorFile are opened. 
        If either of these operations fails a runtime_error exception is thrown. */
        bool readNextValue(T &aValue);
        /* pre: openFiles has been successfully called. 
        post: If a value has been successfully read, aValue holds that value and true is returned. 
        Else, the read operation encountered an end-of-file and false is returned. */
};

#endif

数据测试类.cpp

#ifndef DataTestClass_H
#define DataTestClass_H

#include "DataFilter.cpp"
#include "DataFileReader.cpp"
#include <iostream>
#include <fstream>
#include <string>
#include <exception>
#include <vector>

//---------------------------------------------------------------------------

vector<double> vec;
int rangeErrorCounter = 0;

void printResults() {
    double summa(0), medel(0);
    vector<double>::iterator first, last, it;
    first = vec.begin();
    last = vec.end();
    for (it = first; it != last; ++it)
        summa += *it;
    medel = summa/vec.size();

    cout << "Lästa numeriska värden:\t" << vec.size()+rangeErrorCounter << endl;
    cout << "Värden utanför intervallet:\t" << rangeErrorCounter << endl;
    cout << "Summa:\t\t\t" << summa << endl;
    cout << "Medelvärde:\t\t" << medel << endl;
}

int main(int args[])
{
    DataFileReader<double> dr("Values.dat", "ReadErrors.dat");

    try {
        dr.openFiles();
    }
    catch (runtime_error &rt) {
        cout << "Error reading files: " << rt.what() << endl;
        return 0;
    }

    DataFilter<double> df(&dr, 0.0, 10.0);
    ofstream os("RangeErrors.dat");

    if(os.is_open())
        while(true) {
            double value;
            try {
                while(df.getNextValue(value))
                    vec.push_back(value);
                printResults();
                os.close();
                return 0;
            }
            catch(range_error) {
                rangeErrorCounter++;
                os << value << endl;
            }
        }
    else
        cout << "Couldn't open RangeErrors.dat" << endl;
}

#endif

数据过滤器.cpp

#include "DataFilter.h"

template <typename T>
bool DataFilter<T>::getNextValue(T &aValue) {
    if (fileReader.readNextValue(aValue)) {
        if (aValue > max || aValue < min)
            throw(range_error("Outside of range"));
        return true;
    }
    return false;
}

数据过滤器.h

#ifndef DataFilter_H
#define DataFilter_H
#include "DataFileReader.h"

template <typename T> 
class DataFilter { 

    private: 
        DataFileReader<T> fileReader;
        T min, max;

    public: 
        DataFilter(DataFileReader<T> *aReader, T aMin, T aMax): fileReader(*aReader), min(aMin), max(aMax) {}; 
        /* pre: aReader points to an instance of DataFileReader<T> for which openFiles() has been succesfully called. */ 
        bool getNextValue(T &aValue); // throw (range_error); 
        /* pre: an earlier call to getNextValue() has not returned false. 
        post: true is returned if aValue holds a value read from aReader. If a value could not be read, false is returned. 
        If a value is read but is not within the interval specified by aMin and aMax parameters to the constructor, a range_error exception is thrown. */ 
};

#endif

感谢任何帮助。在 SO 和 Google 上搜索了几个小时后,我仍然感到困惑...

最佳答案

您不能使用dynamic_caststring 变量转换为不是从string 派生的数据类型。这样做是一个编译时错误,您无法在运行时捕获它。

如果你想将一个string值解析成不同的类型,使用istringstream,例如:

if (!(dataFileStream >> readValue)) // did I/O fail?
    return false;
istringstream iss(readValue);
if (!(iss >> aValue)) // did parsing fail?
    return false;
return iss.eof(); // was the entire value consumed?

关于c++ - dynamic_cast 模板类 "invalid target type for dynamic_cast",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26050823/

相关文章:

C++ 字符串 DD :HH:MM:SS to integer data types

c++ - 使此代码正确多态

c++ - 类多态性和相等运算符

c++ - 在断点处而不是最初在 GDB 中发送管道输入

python - 将数据从一个 .exe 传递到另一个

c++ - 我应该如何为遗传算法生成随机数?

c++ - 使用 dynamic_cast 向下转型返回 null

c++ - 试图向下转换 std::vector 中对象的指针

C++设计问题: Passing functions via templates?

c++ - typedef int -> 整数。我可以用 c++ 做 cout-> Print 吗?