我的虚拟函数无法C++工作
My virtual function wont work C++
我已经从我的真实代码中编辑了它,以便更容易理解。
基类:
class MWTypes
{
public:
virtual long get() { return (0); }
};
派生类:(还会有其他类,如 char、double 等。
class TypeLong : public MWTypes
{
public:
TypeLong(long& ref) : m_long(ref) {}
~TypeLong();
long get() { return m_long; }
private:
long& m_long;
};
和存储类:
class RowSet
{
public:
void addElememnt(MWTypes elem);
MWTypes getElement();
std::vector<MWTypes> getVector() { return m_row; }
private:
std::vector<MWTypes> m_row;
};
如何称呼:
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 //
///////////////////////////////////////////////
我认为我在这里是正确的。"foo"的值始终为 0。我有一种感觉,这可能是 Im 存储在向量中的方式,也可能是基本的虚函数,因为它总是返回 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& returned = rowSet.getElement(); // actually illegal, but MSVC will let you do
// lastly I want to get the value in the returned type
long foo = returned.get();
实际上,多态调用必须通过指针或引用进行。
编辑:这不是你唯一的问题。向量存储对象(而不是指针)的事实将对对象进行切片并销毁其类型信息。
有关其他信息,请参阅此常见问题解答条目,以帮助您解决问题并了解如何调用虚拟函数。
根本问题是你正在复制 MWTypes 类型的对象,从而丢失它们特定的子类。如果要使用基类的未知子类的对象,则只能使用指向基类型的指针或引用,而不能使用基类型的实际实例。
没有像 ascanio 的代码所示提供函数"get"的实现(使函数"纯虚拟")将阻止您犯此复制错误,因为如果您这样做,编译器不会让您实例化类 MWTypes(它会说该类是"抽象的")。
您正在遭受切片,因为您的集合存储了基本类型的副本。 每当将某些内容存储到向量中时,您的代码只会切掉基部分,并且忘记其原始类型。
要解决此问题,您可以存储指向 base: std::vector<MWTypes*>
的指针,但随后您必须正确管理实例以避免内存泄漏。
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;
};
然后你需要修复调用addElement()的代码来创建new
实例,并再次获得长的时间:
rowSet.getElement()->get();
你的问题在于这个函数void addElememnt(MWTypes elem);
。它应该是 void addElememnt(MWTypes* elem);
或 void addElememnt(MWTypes& elem);
.这是因为通过按值传递参数,它失去了它的多态性。传递 by-value 调用基类的复制构造函数,并且只复制基类(和 vtable)的内容,而忽略派生类中的其余内容。
此外,如果需要存储某个基类类型的值,则需要考虑使用基类类型的指针列表。
问题出在这里:
class RowSet
{
public:
void addElememnt(MWTypes elem);
您是按值获取elem
,而不是通过指针或引用,因此TypeLong
子对象被切掉,如下所示:(参考:C++中的切片问题是什么?
TypeLong longObj(_long);
MWTypes *ptr = &longObj;
_long++;
rowSet.addElememnt(*ptr);
您需要更改addElement
以获取引用或指针。
您的vector
、getElement
和addElememnt
部分都调用对象切片,因为它们按值存储基本对象。您需要使用指针或引用才能使用运行时多态性。
在这种情况下,boost::ptr_vector
或shared_ptr
的vector
可能是您想要的。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 为什么stream::忽略未按预期工作