chikuba
chikuba

Reputation: 4357

Use the derived class value from the base class

Trying to create a widget in the baseclass and the only thing that will change in the widget depending on what derived class we call is the title.

class BaseView : public QWidget {
    Q_OBJECT
public:
     explicit BaseView(QWidget *parent = 0);
protected:
     QString title; 
     virtual QString getTitle() const {
         return title;
     }

BaseView.cpp :

BaseView::BaseView(QWidget *parent) : QWidget(parent) {

     title = "test"
}

void BaseView::createTopWidget() {
    QGroupBox *topWidget = new QGroupBox(getTitle());
    ....
}

The in the derived class header:

class DerivedView : public BaseView {
    Q_OBJECT
public:
     explicit DerivedView(QWidget *parent = 0);
protected:
     QString getTitle() const {
         return title;
     }

And in the derived constructor I set title to "correct".

When I run the program by creating a DerivedView, the title is still "test". How can I do this so I will call and get at derived class value from the base class?

Upvotes: 1

Views: 139

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 477690

Unless you have a very firm grasp on C++, you must not call virtual functions in a constructor. The problem is that during subobject creation, the type of the object is the base subobject, not the derived object, so the virtual function call is dispatched to the "wrong" function.

Baby example:

struct Base
{
    virtual int foo() { return 8; }

    Base() { set_something(foo()); }  // who're you gonna call?
};
struct Derived
{
    virtual int foo() { return -12; }
};

Derived d;

Now in the base constructor for d.Base(), the function that gets called is d.Base::foo(), not d.Derived::foo().

Moreover, by the time the base class constructor runs, the member variable title has only been set to "test", and it has not yet been overwritten by the assignment in the derived constructor, which runs only after the base constructor completes.

You can solve your problem by passing the title in the constructor explicitly:

class BaseView : public QWidget
{
public:
    BaseView(QWidget * parent = 0, QString const & t = "test")
    : QWidget(parent), title(t)
    {
        something.set_title(title);
    }

    // ...
};

class DerivedView
{
public:
    DerivedView(QWidget * parent = 0)
    : BaseView(parent, "correct")
    { }
};

Upvotes: 2

Related Questions