如何根据用户输入设置矢量的类型
How to set a vector's type based on user input
我想避免为不同类型编写整个程序。这就是代码现在的样子:
switch(e) {
case('i'): { // if the user wants integers:
std::vector<long double> v(b);
std::cout << "nEnter the Minimum Size for the numbers: ";
std::cin >> c;
std::cout << "nEnter the Maximum Size for the numbers: ";
std::cin >> d;
for (i = 0; i <= b-1; i++)
a[i] = random_int(c, d);
.
.
.
sort(a.data(), 0,b-1);
break;
}
case('d'): { // if the user wants decimal numbers:
std::vector<long double> v(b);
std::cout << "nEnter the Minimum Size for the numbers: ";
std::cin >> m;
std::cout << "nEnter the Maximum Size for the numbers: ";
std::cin >> n;
for (i = 0; i <= b-1; i++)
a[i] = random_float(m, n);
.
.
.
sort(v.data(), 0,b-1);
break;
}
default: {
goto loop;
break;
}
}
正如你所看到的,它是不必要的长。
改变矢量的类型似乎不起作用(很难),而且由于random_int
/random_float
部分(他们使用std::uniform_int_distribution
和std::uniform_real_distribution
),我无法创建用于生成矢量的函数。
有很多方法可以做到这一点,但没有一种"最佳方法"。但最直接的方法可能是使用继承。根据类型列出所有必须更改的行为,并为每个行为实现函数。多形态地实现它们。例如:
class IntOrDouble
{
public:
bool isInt() const { return _isInt; }
bool isDouble() const { return !_isInt; }
int getAsInt() const; // throws if not integer
double getAsDouble() const; // throws if not double
protected:
bool _isInt;
int _valueIfInt;
double _valueIfDouble;
};
class VectorOfIntsOrDoubles
{
public:
void makeVectorOfInts(); // must be empty
void makeVectorOfDoubles(); // must be empty
// Reads an IntOrDouble of the appropriate type for this container
IntOrDouble ReadValue() const;
// Generates a random IntOrDouble of the appropriate type for this container
IntOrDouble GenRandom() const;
private:
bool _isInts;
std::vector <IntOrDouble> _vector;
};
等等。
另一种多态方法。首先,我们定义了一个抽象基类,这是只有程序的大多数部分才会知道的。它只定义对数据的访问函数,不包含任何函数(除了kind
类型标记)。派生类的大多数访问函数实现只会在运行时抛出,但适用于元素数据类型的实现除外:
/// The type which will alwys be returned
class VecHolder
{
public:
enum kindE { INTVEC, DBLVEC, /*...*/} ;
kindE kind;
VecHolder(kindE k) : kind(k) {}
/// These expose the vectors for simplicity. The derived classes
/// will hold just one of them.
virtual vector<int> &intVec() = 0;
virtual vector<double> &dblVec() = 0;
// ...
static VecHolder *MakeVec(kindE kind);
};
现在,我们将展示两个具体的实现,用于double和int:
/// An implementation for int elements
class IntVecHolder: public VecHolder
{
public:
IntVecHolder() : VecHolder(INTVEC) {}
vector<int> &intVec() { return vec; };
vector<double> &dblVec() { throw exception();}
protected:
vector<int> vec;
};
/// An implementation for double elements
class DblVecHolder: public VecHolder
{
public:
DblVecHolder() : VecHolder(DBLVEC) {}
vector<int> &intVec() { throw exception();}
vector<double> &dblVec(){ return vec; };
protected:
/// This is the actual data (somewhat) hidden behind the
/// abstract VecHolder interface.
vector<double> vec;
};
既然我们知道了这些类,我们就可以对工厂函数进行编码,该函数根据用户的选择创建适当的VecHolder实现(kind
):
/// The factory function: Exact type of object behind returned
/// pointer dpends on parameter, but they are all derived from VecHolder
VecHolder *VecHolder::MakeVec(kindE kind)
{
switch(kind)
{
case INTVEC: return new IntVecHolder; break;
case DBLVEC: return new DblVecHolder; break;
}
}
最后,这里是一个使用示例。我发现这比我想象的更尴尬——用户代码总是必须根据持有者的kind
进行区分。当然,人们应该尽可能多地隐藏函数中丑陋的切换。
int main()
{
/// An array of vec holder pointers
VecHolder *vecHolders[]
{ VecHolder::MakeVec(VecHolder::DBLVEC),
VecHolder::MakeVec(VecHolder::INTVEC)
};
for( auto &vhp: vecHolders )
{
// we always have to discriminate.
switch(vhp->kind)
{
case VecHolder::DBLVEC: vhp->dblVec().push_back(1.0); break;
case VecHolder::INTVEC: vhp->intVec().push_back(2); break;
}
}
for( auto &vhp: vecHolders )
{
switch(vhp->kind)
{
case VecHolder::DBLVEC:
cout << vhp->dblVec()[0] << endl;
break;
case VecHolder::INTVEC:
cout << vhp->intVec()[0] << endl;
break;
}
// clean up
delete vhp;
}
}
示例会话:
$ g++ -std=c++11 -o polymorphic-vec polymorphic-vec.cpp && ./polymorphic-vec
1
2
相关文章:
- C++(和 ROS) - 包含与前向声明引用,设置默认值和类型定义
- std::ifstream 在读取文件中最后一项时设置 eofbit,但仅在读取数值类型时发生
- Poco 库 PUT 方法未按预期工作,尽管主机、方法、内容类型设置正确
- 无法在 HEVC 解码器上设置输出类型 IMFTransform
- Visual Studio 2019 - 设置文件类型的默认扩展名
- 无法在VSCode中设置C++调试;无法识别调试类型
- 将变量设置为类型模板
- 在 C++ 中设置的用户定义数据类型
- 为自定义路径类型设置提升property_tree
- C++:无法在按位函数后将 int 类型设置为非标量
- 为什么我不能为位于基类中的类中的类型设置别名
- 可以将枚举的默认类型设置为无符号字符
- 有没有办法使用显式实例化按类型设置成员变量
- C++中用于将默认变量类型设置为int的任何选项
- 是否可以继承模板类并将类型设置为当前尝试从中继承的类的模板化子类?
- 如何使用 std::conditional 根据模板参数类型设置类型
- 事件类型设置为SDL_MOUSEBUTTONDOWN,即使在未按下任何按钮时也是如此
- std::使用自定义类型设置差异
- 为具有多重继承的一个类型设置默认构造函数
- 如何为特定的模板数据类型设置条件