c++ - 只在运行时知道数据类型。如何向使用它们的其他类隐藏数据详细信息

标签 c++ c++11 runtime std

基本上我必须使用以下语法根据输入文本文件填充对象:

float 4.55 24 2.1
int 4 6 9 0
float 5.1 6 6
//char 255 3 5

然后我需要对它们进行某种操作(例如简单的加法),没有办法事先知道会有哪些类型的数据。

我不能在内部将它们全部存储为 double 变量,因为空间优化很重要,而且不会失去精度。

我想做这样的事情:

class Base {
public:
    virtual size_t size() = 0;
    virtual void addValue () = 0;
    virtual void getValue (int index) = 0;
};

class BaseFloat : public Base{
public:
    vector<float> data;
    void addValue (float d);
    float getValue (int index);
    size_t size();
}

class BaseInt : public Base{
public:
    vector<int> data;
    void addValue (int d);
    Int getValue (int index);
    size_t size();
}
/* other classes for each data type here*/

这行不通,因为每个函数都有不同的返回类型或参数需求;

然后我有一个类为每一行创建正确的对象。

当我需要其他可以与任何类型的 Base 一起工作的类时,问题就来了。我在想类似的事情:

class OtherClass {
public:
    void addValue(Base*, double);
}

OtherClass my_class; //whatever
Base* a = new BaseFloat ();
Base* b = new BaseInt();

my_class.addData(a, 5.56); //Uses BaseFloat::addValue
my_class.addData(b, 6);  //Uses BaseInt::addValue
my_class.addData(b, 6.55); //Uses BaseInt::addValue

我希望我可以在不添加某种长 if-else 子句的情况下做到这一点 喜欢:

void OtherClass::addDataHelper (Base* pointer)
if (subclass(pointer) == float)
    //Do BaseFloat* a = pointer;
    //Do a->addValue
else if ...

有什么想法吗?

最佳答案

当您创建 OO 设计时,您需要定义基类的接口(interface),因此所有派生类都可以覆盖虚函数而无需更改签名。例如读取数据可以这样实现:

class BaseData {
public:
    virtual bool addValue( std::istream &in ) = 0;
};

class DataFloat : public BaseData {
    virtual bool addValue( std::istream &in ) override
    {
         float v = 0;
         if( not in >> v ) return false;
         data_.push_back( v );
         return true;
    }
private:
    std::vector<float> data_;
};

class Factory {
public:
    std::unique_ptr<BaseData> create( const std::string &type );
};

std::vector<std::unique_ptr<BaseData>> parsing( std::istream &in, Factory &f )
{
    std::vector<std::unique_ptr<BaseData>> v;
    std::string str;
    while( std::getline( in, str ) ) {
        std::istringstream line( str );
        std::string type;
        if( not in >> type ) continue;
        auto pbase = f.create( type );
        while( pbase->addValue( in ) );
        v.push_back( std::move( pbase ) );
    }
    return v;
}

当然这不是完整的代码,但应该足以展示这个想法。因此,对于您的操作,您需要做同样的事情——找到在基类中定义虚函数的方法,这样它就可以在每个派生类中重新实现,而无需更改签名。您对每个类(class)的处理方式 void addValue( int data )void addValue( float data )不是正确的 OO 设计,会导致级联 ifdynamic_cast或类似的方法。

另一种解决方案是在 std::vector<std::variant<int,float,char,double>> 中获取数据(列出了所有必要的类型)并编写适当的访问者来进行数据插入和计算等。互联网上有很多关于如何正确执行此操作的 Material ,将它们添加到此处将超出此答案的范围。

关于c++ - 只在运行时知道数据类型。如何向使用它们的其他类隐藏数据详细信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51546153/

相关文章:

c++ - 根据文件读取条件初始化struct中char的大小

c++ - 如何在编译时将 C 字符串转换为 int?

c++ - 在类内部处理回调时必须调用非静态成员函数的引用

c++ - 返回并自动推导 std::initializer_list

c - 从 C 程序中运行 C 程序

java - 从 IntelliJ Ultimate 外部运行时,Tomcat 的 "server log"在哪里?

c++ - 类成员模板函数的名称实例

c++ - 构造函数中的智能指针

c++ - 在 C++ 中创建库

java - Java中编译C的时间间隔定义