我想避免为不同类型编写整个程序。这就是代码现在的样子:
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
)。
答案 0 :(得分:1)
有很多方法可以做到这一点,而且没有一种“最佳方式”。但最直接的方法可能是使用继承。根据每个行为的类型和实现函数,列出必须更改的所有行为。多态地实现它们。例如:
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;
};
等等。
答案 1 :(得分:0)
另一种多态方法。首先,我们定义一个抽象基类,这是程序的大多数部分才会知道的。它仅定义数据的访问函数,不包含任何(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和for 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;
};
现在我们知道了这些类,我们可以编写工厂函数,根据用户的选择(kind
)创建适当的VecHolder实现:
/// 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