1

I have following very simple Qt project:

I have

#ifndef ABSTRACTWIDGET_H
#define ABSTRACTWIDGET_H

#include <QWidget>
#include <QVariant>

namespace Ui {
  class AbstractWidget;
}

class AbstractWidget : public QWidget
{
  Q_OBJECT

public:
  explicit AbstractWidget(const QString &name, QWidget *parent = 0);
  ~AbstractWidget();

  QString getName();

  virtual void setValue(const QVariant & value);

protected:
  Ui::AbstractWidget *ui;

};

#endif // ABSTRACTWIDGET_H

and

#ifndef SLIDERWIDGET_H
#define SLIDERWIDGET_H

#include "abstractwidget.h"

#include <QSlider>

class SliderWidget : public AbstractWidget
{
  Q_OBJECT

public:
  explicit SliderWidget(const QString & name, int min, int max, QWidget *parent = 0);
  ~SliderWidget();

  void setValue(const QVariant & value);

private:
  QSlider * slider;

};

#endif // SLIDERWIDGET_H 

I just made setValue virtual at the super class Abstractwidget, which drops follwing linker error:

moc_abstractwidget.cpp:-1: Fehler: undefined reference to `AbstractWidget::setValue(QVariant const&)'

collect2.exe:-1: Fehler: error: ld returned 1 exit status

Rebuilding All and Cleaning up did not help. Why is it failing to link?

  1. Abstract is a bad nomencalture, sorry my bad. Consider it as a super class (not abstract) from which I derive other classes.

  2. I inject in a MainWindow::Ui::QVBoxLayout dynamically those AbstractWidget classes (for instance I have multiple SliderWidgets and ColorPickerWidget : public Abstractwidget as well). I just wanted to keep it simple.

  3. Why derive? I have multiple QWidgets (besides SliderWidget) deriving from AbstractWidget class. All of them have a QString name. I wanted to provide that name in the base class ==> AbstractWidget.

  4. Why virtual void setValue(): Every derived class has somesting like a slider, colorpicker etc. I implement in each derived class a setValue(QVariant) so that the colorpicker sets the QColor(QVariant::toString()) and the SliderWidget sets the sliderValue with setValue(QVariant::toInt()), etc.. setValue is public everywhere (virtual base class and derived implementations).

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
Ralf Wickum
  • 2,850
  • 9
  • 55
  • 103
  • Is the method implemented in the cpp file? – dtech Sep 01 '15 at 17:18
  • Also, I see you are inheriting from a widget, build with the UI designer. I am not sure if that is legal at all, haven't tried it, but it sounds as a possible issue source. – dtech Sep 01 '15 at 17:19
  • @ddriver It is not implemented in the super class where it is defined as virtual. In the derived classes it is implemented, but not with the very same parameter signature. . – Ralf Wickum Sep 01 '15 at 17:20
  • @ddriver Before I added and implenented the virtual void setValue() it was working properly. – Ralf Wickum Sep 01 '15 at 17:22
  • "I added and implenented the virtual void setValue()" You don't show the implementation anywhere in the question. It is missing from your code - the linker is telling you as much. You're implementing something else, perhaps, but not this particular method. The reimplementation in `SliderWidget` should be marked `Q_DECL_OVERRIDE` to ensure you're not merely hiding the base class's method due to a typo. – Kuba hasn't forgotten Monica Sep 01 '15 at 17:29
  • @Kuba Ober Implementation of setValue in the derived class: void SliderWidget::setValue(const QVariant &value) { slider->setValue( value.toInt() ); } – Ralf Wickum Sep 01 '15 at 17:33
  • Finally, all you seem to be doing is adding some unnecessary glue to the Qt Meta Property system. Most controls, such as sliders, have a single user property that can be programmatically changed without knowing anything about the particular object's type. See [this answer](http://stackoverflow.com/a/18964614/1329652) for how to get at the user property. – Kuba hasn't forgotten Monica Sep 01 '15 at 17:33
  • @RalfWickum What about the base class? The "abstract" class isn't abstract, you have to implement `AbstractWidget::setValue`. – Kuba hasn't forgotten Monica Sep 01 '15 at 17:33
  • 1
    @RalfWickum - if you don't want to provide an implementation for a virtual method, you should mark it as abstract with `= 0;` at the end. This will prevent the compiler from complaining it cannot find its definition. – dtech Sep 01 '15 at 17:36
  • "All of them have a QString name" All `QObject`s have names - it's the `objectName` property. Why add another one? "setValue(QVariant) so that the colorpicker sets the QColor(QVariant::toString())" You can implement a `setValue(QWidget*)` that works on any widget with a user property, as a free-standing function. No need to have a different one in each widget. I'll unmark this as a duplicate since the real problem is not the trivial linking issue, but the design issue. – Kuba hasn't forgotten Monica Sep 02 '15 at 15:24
  • Since the original problem is truly a duplicate, would you be willing to edit the question to ask about whether such a design could be improved instead? This would save it from deletion and turn it into something useful for others. Sometimes inheritance is not needed, or at least not needed in the intrusive form provided. I believe that this is the case here. – Kuba hasn't forgotten Monica Sep 02 '15 at 15:27

0 Answers0