[Qt-interest] Problem with undefined VTable when subclassing QSpinBox?

kent williams nkwmailinglists at gmail.com
Fri Jul 23 21:17:04 CEST 2010


I know (from web research) that the cause of the undefined external
for vtable comes from a class not having virtual class member
functions declared but not defined.   But in this case I can't see
where I screwed this up.

The problem I was trying to solve was that I wanted to have a QSpinbox
that would allow the user to choose from a set of predefined choices.
My particular application was to have a spinbox that allowed the user
to choose between different Pixel types for an image (unsigned char,
signed short, signed long, float).

According to the documentation you can do this by deriving a class
from QSpinBox and redefine valueFromText and textFromValue.  So I did
so; I'll include the code below.  The problem is that now my
application fails to link:

Undefined symbols:
  "vtable for QEnumSpinBox", referenced from:
      QEnumSpinBox::~QEnumSpinBox()in QEnumSpinBox.cxx.o
      QEnumSpinBox::QEnumSpinBox(QWidget*)in QEnumSpinBox.cxx.o
 d: symbol(s) not found

I've spent hours looking at my implementation and I can't see the
problem. Anyone want to give me some pointers?

--------------------------QEnumSpinBox.h---------------------------------------------------------

#define QEnumspinbox_h
#include <QSpinBox>
#include <QValidator>
#include <QStringList>

class QEnumSpinBox : public QSpinBox
{
  Q_OBJECT
public:
  QEnumSpinBox(QWidget *parent = 0);
  virtual ~QEnumSpinBox();
  void SetValue(const std::string &s);
  void SetEnumVals(const char **list);
protected:
  virtual QValidator::State validate(QString &input, int &pos) const;
  virtual int valueFromText(const QString &text) const;
  virtual QString textFromValue(int val) const;
  virtual void fixup(QString &str) const;
private:
  QStringList m_QEnumVals;
};

#endif // QEnumspinbox_h
-------------------------------QEnumSpinBox.cxx----------------------------------------------------

#include "QEnumSpinBox.h"

QEnumSpinBox::
QEnumSpinBox(QWidget *parent) : QSpinBox(parent)
{
}
QEnumSpinBox::
~QEnumSpinBox()
{
}

QValidator::State
QEnumSpinBox::
validate(QString &text, int &pos) const
{
  QStringList::const_iterator it;
  // compare to each QEnum until a match is found or not found
  for(it = this->m_QEnumVals.constBegin();
      it != this->m_QEnumVals.constEnd();
      ++it)
    {
    // text substring of current?
    if(text.size() < (*it).size())
      {
      QString tmp((*it));
      tmp.chop((*it).size() - text.size());
      if(text == tmp)
	{
	return QValidator::Intermediate;
	}
      }
    // exactly equal?
    else if(text == (*it))
      {
      return QValidator::Acceptable;
      }
    }
  return QValidator::Invalid;
}

void
QEnumSpinBox::
SetValue(const std::string &s)
{
  QString qs(s.c_str());
  for(int i = 0; i < this->m_QEnumVals.size(); i++)
    {
    if(qs == this->m_QEnumVals[i])
      {
      this->setValue(i);
      break;
      }
    }
}

void
QEnumSpinBox::
SetEnumVals(const char **list)
{
  for(unsigned i = 0; list[i] != 0; list++)
    {
    this->m_QEnumVals.push_back(QString(list[i]));
    }
}

int
QEnumSpinBox::
valueFromText(const QString &text) const
{
  QStringList::const_iterator it;
  // compare to each QEnum until a match is found or not found
  unsigned i = 0;
  for(it = this->m_QEnumVals.constBegin();
      it != this->m_QEnumVals.constEnd();
      ++it,++i)
    {
    if(text == (*it))
      {
      return i;
      }
    }
  return -1;
}

QString
QEnumSpinBox::
textFromValue(int value) const
{

  if(value < this->m_QEnumVals.size())
    {
    return this->m_QEnumVals[value];
    }
  return QString("INVALID");
}

void
QEnumSpinBox::
fixup(QString &str) const
{
  this->QSpinBox::fixup(str);
}



More information about the Qt-interest-old mailing list