我正在尝试为不同大小的矩阵和向量创建模板类。 对于我的Vector类,我重载了+ =和+运算符,以便能够添加两个相同长度的向量。如果长度不匹配,我希望编译器抛出错误。 我想将多个mvc :: Vector对象(具有不同的长度)存储在std :: vector中。 为此,我创建了一个基类mvc :: VectorBase,该基类继承了所有mvc :: Vector对象。 现在我可以写
std::vector<std::unique_ptr<mvc::VectorBase>> vectorBuffer;
为了能够从vectorBuffer调用MyVector的成员函数,我为这些成员添加了纯虚函数,以便可以使用
vectorBuffer[0]->GetLength().
我的问题: 我无法编写代码,因为VectorBase不知道运算符重载。
mvc::Vector<2> result = (*vectorBuffer[0]) + (*vectorBuffer[1]);
试图将运算符重载作为纯虚函数添加到mvc :: VectorBase无效,因为一个参数必须是mvc :: Vector模板类的模板参数,我不能在模板之外使用。
#include <vector>
#include <memory>
#define T float
namespace mvc
{
class VectorBase
{
public:
// virtual Vector operator+= (Vector<Tlength>& other) = 0;
virtual int GetLength() const = 0;
};
template<int Tlength>
class Vector : public VectorBase
{
private:
T vec[Tlength];
public:
Vector operator+ (Vector<Tlength>& other)
{
for (int i = 0; i < Tlength; i++)
{
vec[i] += other.vec[i];
}
return *this;
}
int GetLength() const
{
return Tlength
}
}
}
int main()
{
mvc::Vector<3> vec3_1;
mvc::Vector<3> vec3_2;
mvc::Vector<4> vec4_1;
mvc::Vector<3> result = vec3_1 + vec3_2; // this line works properly
mvc::Vector<3> result = vec3_1 + vec4_1; //this line won´t compile (as expected)
std::vector<std::unique_ptr<mvc::VectorBase>> vectorBuffer;
vectorBuffer.push_back(std::make_unique<mvc::Vector<2>>());
vectorBuffer.push_back(std::make_unique<mvc::Vector<2>>());
mvc::Vector<2> result = (*vectorBuffer[0]) + (*vectorBuffer[1]); // <-- this is what i want to be able to do
}
如何实现所需的行为: 只有在使用相同模板(Tlength相等)生成MyVector对象的情况下,vectorBuffer [0] + vectorBuffer [1]才有效
这已经可以用于MyVector的两个单独存储的实例。 当我使用多态性将多个mvc :: Vector对象存储在同一std :: vector中时,它将失败。
编辑: 通过使用基类作为返回类型重载+运算符,我得到了请求的行为:
#include <vector>
#include <memory>
#include <iostream>
#define T float
namespace mvc
{
class VectorBase
{
public:
virtual VectorBase* operator+ (VectorBase& other) = 0;
virtual int GetLength() const = 0;
virtual T GetElem(int i) const = 0;
virtual void Print() const = 0;
};
template<int Tlength>
class Vector : public VectorBase
{
private:
T vec[Tlength];
public:
Vector(T initValue)
{
for (int i = 0; i < Tlength; i++)
{
vec[i] = initValue;
}
}
VectorBase* operator+ (VectorBase& other) override
{
if (other.GetLength() != Tlength)
{
std::cout << "[Error]: Argument dimensions mismatch. Program will terminate." << std::endl;
std::cin.get();
exit(-1);
}
//Vector<Tlength> tmpOther = dynamic_cast<Vector<Tlength>&>(other);
for (int i = 0; i < Tlength; i++)
{
//vec[i] += tmpOther.vec[i];
vec[i] += other.GetElem(i);
}
return this;
}
Vector<Tlength> operator+ (Vector<Tlength>& other)
{
for (int i = 0; i < Tlength; i++)
{
vec[i] += other.GetElem(i);
}
return *this;
}
int GetLength() const override
{
return Tlength;
}
T GetElem(int i) const override
{
return vec[i];
}
void Print() const override
{
for (int i = 0; i < Tlength; i++)
{
std::cout << " " << vec[i] << "\n";
}
std::cout << std::endl;
}
};
}
int main()
{
/* without polymorphism */
// vector1
mvc::Vector<2> vec3_1 = mvc::Vector<2>(1.2f);
vec3_1.Print();
// vector2
mvc::Vector<2> vec3_2 = mvc::Vector<2>(3.4f);
vec3_2.Print();
// vector2 = vector1 + vector2
vec3_2 = vec3_1 + vec3_2;
vec3_2.Print();
/* with polymorphism */
// vector buffer storing base class objects
std::vector<mvc::VectorBase*> vectorBuffer;
//vector1
vectorBuffer.push_back(new mvc::Vector<3>(3.5f));
vectorBuffer[0]->Print();
//vector2
vectorBuffer.push_back(new mvc::Vector<3>(2.8f));
vectorBuffer[1]->Print();
//vector2 = vector1 + vector2
vectorBuffer[1] = *vectorBuffer[0] + *vectorBuffer[1];
vectorBuffer[1]->Print();
std::cin.get();
for (unsigned int i = 0; i < vectorBuffer.size(); i++)
{
delete vectorBuffer[i];
}
}
plus运算符被两次重载,以也支持“非逻辑变形”用法。 (请参阅main内部的示例)
使用@Vikas Awadhiya的dynamic_cast解决方案来赞扬操作员+覆盖。这也有效。与当前使用虚拟吸气功能GetElem的解决方案相比,目前我不了解性能。
目前,我只能使它与原始指针一起使用。仍在研究unique_ptr解决方案。
感谢所有回复!
答案 0 :(得分:0)
我在代码上所做的更改很少,
#include <iostream>
#include <vector>
#include <memory>
namespace mvc
{
class VectorBase
{
public:
virtual ~VectorBase(){}
virtual VectorBase& operator+ ( VectorBase& other) = 0;
virtual int GetLength() const = 0;
};
template<int length>
class Vector: public VectorBase
{
private:
double vec[length];
public:
Vector(): VectorBase(),
vec{}
{
}
VectorBase& operator+ ( VectorBase& other) override
{
Vector< length>& subOther = dynamic_cast< Vector< length>&>( other);
for ( int i = 0; i < length; i++)
{
vec[i] += subOther.vec[ i];
}
return *this;
}
int GetLength() const
{
return length;
}
};
}
int main()
{
std::vector<std::unique_ptr<mvc::VectorBase>> vectorBuffer;
vectorBuffer.push_back( std::make_unique<mvc::Vector< 2>>());
vectorBuffer.push_back( std::make_unique<mvc::Vector< 2>>());
mvc::Vector< 2> result = dynamic_cast< mvc::Vector< 2>&>( *vectorBuffer[ 0] + *vectorBuffer[ 1]);
std::cout<< "result.length = "<< result.GetLength()<< std::endl;
}
输出:result.length = 2
答案 1 :(得分:0)
您可以通过使虚拟operator+
返回并接受基类来做到这一点:
class VectorBase
{
public:
virtual int GetLength() const = 0;
// We have to return a heap allocated object because the actual type and,
// hence, its size is unknown
virtual std::unique_ptr<VectorBase> operator+(VectorBase& other) = 0;
};
template<int Tlength>
class Vector: public VectorBase
{
private:
// ...
std::unique_ptr<VectorBase> operator+(VectorBase& other) override
{
if (other.GetLength() != Tlength)
return nullptr; // or throw an exception if you want
Vector result = *this + static_cast<Vector<Tlength>&>(other);
// or "new Vector<Tlength>(result)" if your compiler doesn't support C++14
return std::make_unique<Vector<Tlength>>(result);
}
// ...
};