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++0x
std::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();