C++ 我的虚拟函数无法使用C++;
我从我的真实代码中编辑了这个,所以它更容易理解 基类:C++ 我的虚拟函数无法使用C++;,c++,inheritance,vector,polymorphism,virtual,C++,Inheritance,Vector,Polymorphism,Virtual,我从我的真实代码中编辑了这个,所以它更容易理解 基类: class MWTypes { public: virtual long get() { return (0); } }; 派生类:(还有其他类,如char、double等…) 以及存储类: class RowSet { public: void addElememnt(MWTypes elem); MWTypes getElement(); std::vector<MWTypes> getV
class MWTypes
{
public:
virtual long get() { return (0); }
};
派生类:(还有其他类,如char、double等…)
以及存储类:
class RowSet
{
public:
void addElememnt(MWTypes elem);
MWTypes getElement();
std::vector<MWTypes> getVector() { return m_row; }
private:
std::vector<MWTypes> m_row;
};
类行集
{
公众:
无效补遗(mwelem);
mwType getElement();
std::vector getVector(){return m_row;}
私人:
std::向量m_行;
};
如何称呼它:
for (i = 0; i < NumCols; i++) // NumCols is 3 on this instance
{
switch(CTypeArray[i]) // this is an int which identifies the type
{
case SQL_INTEGER:
{
long _long = 0;
TypeLong longObj(_long);
MWTypes *ptr = &longObj;
// some SQL code goes here that changes the value of _long,
// there is no need to include it, so this will do.
_long++;
// I now want to save the data in a vector to be returned to the user.
rowSet.addElememnt(*ptr);
///////////////////////////////////////////////
// some code happens here that is irrelevant //
///////////////////////////////////////////////
// I now want to return the typr I have saved in the vector,
// I THINK I am doing this right?
MWTypes returned = rowSet.getElement();
// lastly I want to get the value in the returned type
long foo = returned.get();
///////////////////////////////////////////////
// some code happens here that is irrelevant //
///////////////////////////////////////////////
(i=0;ifor//NumCols在此实例上为3
{
开关(CTypeArray[i])//这是一个标识类型的int
{
案例SQL\u整数:
{
long _long=0;
TypeLong longObj(_long);
MWTypes*ptr=&longObj;
//这里的一些SQL代码更改了_long的值,
//没有必要包括它,所以这样就可以了。
_long++;
//现在,我想将数据保存在一个向量中,以返回给用户。
行集。补遗(*ptr);
///////////////////////////////////////////////
//这里发生了一些不相关的代码//
///////////////////////////////////////////////
//现在我想返回我保存在向量中的typr,
//我想我做得对吗?
返回的MWTypes=rowSet.getElement();
//最后,我想获取返回类型中的值
long foo=returned.get();
///////////////////////////////////////////////
//这里发生了一些不相关的代码//
///////////////////////////////////////////////
我想我在这里是对的。“foo”的值总是0。我有一种感觉,这可能是我在向量中存储的方式,也可能是基本虚函数,因为它总是返回0
如果我删除基类中的返回,我会得到LNK2001错误
MWTypes returned = rowSet.getElement();
// lastly I want to get the value in the returned type
long foo = returned.get();
应该是
MWTypes* returned = &rowSet.getElement();
// lastly I want to get the value in the returned type
long foo = returned->get();
或
实际上,多态调用必须通过指针或引用进行
编辑:这不是您唯一的问题。向量存储对象(而不是指针)的事实将损坏对象并破坏其类型信息
有关帮助您解决问题和理解如何调用虚拟函数的其他信息,请参阅。您的问题在于此函数
无效加法元素(MWTypes elem);
。它应该是无效加法元素(MWTypes*elem);
或无效加法元素(MWTypes&elem)
。这是因为通过值传递参数,它会丢失其多态性。通过值传递调用基类的复制构造函数,只复制基类(和vtable)的内容,而忽略派生类的其余内容
此外,如果需要存储某个基类类型的值,则需要考虑使用基类类型的指针列表。
问题在于:
class RowSet
{
public:
void addElememnt(MWTypes elem);
您是通过值而不是指针或引用获取elem
,因此TypeLong
子对象被切掉,这里:(reference:)
您需要更改
addElement
以获取引用或指针。您的向量
、getElement
和addElement
部分都调用对象切片,因为它们按值存储基本对象。为了使用运行时多态性,您需要使用指针或引用
在这种情况下,您可能需要
boost::ptr_vector
或shared_ptr
的vector
。由于您的集合存储基本类型的副本,您正遭受切片的痛苦。每当您将某些内容存储到向量中时,您的代码只会将基本部分切掉,而忘记其原始类型。>
要解决此问题,可以存储指向基:std::vector
的指针,但必须正确管理实例以避免内存泄漏
class RowSet
{
public:
// addElement assumes responsibility for the memory allocated for each 'elem'
void addElement(MWTypes* elem);
MWTypes* getElement();
std::vector<MWTypes*> getVector() { return m_row; }
// Destructor calls delete on every pointer in m_row
~RowSet();
private:
std::vector<MWTypes*> m_row;
};
基本问题是,您正在复制MWTypes类型的对象,从而丢失它们的特定子类。如果要使用基类未知子类的对象,则只能使用指向该基类的指针或引用,而不能使用该基类的实际实例
如ascanio的代码所示,不提供函数“get”的实现(使函数“纯虚拟”)将防止您犯这种复制错误,因为如果您这样做,编译器将不允许您实例化类MWTypes(它会说该类是“抽象的”).不应在接口中实现虚拟函数get()(返回(0);).@ascanio:你不知道。@PoiXen的真实代码可能不要求基类是抽象的。@John:同意,但这将诊断这里的问题,因为它将涉及实例化抽象类。此外,@PoiXen的一个警告可能是他正在堆栈上创建一个
longObj
,并持有一个引用如果这段代码离开了longObj
@birryrree:是的,但实际上,OP有更糟糕的问题。请参阅我的编辑。哦,这是一个好的调用,这也会带来拥有正确副本构造函数的问题-虽然在提供的代码中这不会是一个问题,但他仍然在中绑定引用>TypeLong
类,这是我最初没有看到的问题。您的修改不会带来任何好处。您可以用long foo=0;
替换最后一行代码,因为您只处理基类,它的get()
始终返回0。MWTypes*returned=&rowSet.getElement()
nooooooon不仅仅是addElement
:即使你修改了add,向量本身和返回函数也会被切分。@马克:可能是真的。我刚刚阐述了我看到的第一个问题。这是正确的,先生。除了你缺少析构函数和复制语义之外。最好的解决方案是boost::ptr\u vector
或C++0xstd::unique_ptr
@AlexandreC:行集的析构函数
class RowSet
{
public:
void addElememnt(MWTypes elem);
TypeLong longObj(_long);
MWTypes *ptr = &longObj;
_long++;
rowSet.addElememnt(*ptr);
class RowSet
{
public:
// addElement assumes responsibility for the memory allocated for each 'elem'
void addElement(MWTypes* elem);
MWTypes* getElement();
std::vector<MWTypes*> getVector() { return m_row; }
// Destructor calls delete on every pointer in m_row
~RowSet();
private:
std::vector<MWTypes*> m_row;
};
rowSet.getElement()->get();