hr0m
hr0m

Reputation: 2805

Override initial value of a member variable of base class

I am very confused with the inheritance right now. I planned to simply override the initial value of a variable. In the following code i just inherit the base class and try to get it's name, which is saved as a string withing the class. I expected that the derived class can override this value, however it does not do it.

My expected out put was

Derived
Derived

However i get

Base
Base

What is the correct way to implement the following?

#include <iostream>
#include <string>

struct Base {
    virtual ~Base() = default;
    virtual void id(){
        std::cout << id_ << std::endl;
    }
    std::string id_ = "Base";
};   



struct Derived : public Base {
    virtual ~Derived() = default;
    std::string id_ = "Derived";
};   


int main(){
    Base* b = new Derived();
    Derived* d = new Derived();
    b->id();
    d->id();
    delete d;
    delete b;                                                                                                          
    return 0;
}

Upvotes: 5

Views: 6720

Answers (4)

cpp_learner
cpp_learner

Reputation: 382

Since function id() is virtual, in both case object pointer is Derived type only.

Base* b = new Derived(); // object type is Derived
b->id();

here b is pointer of type Derived but the "Derived" class has no implementation for id(), since there is no entry for id() in virtual lookup table for derived class object so it will call base class function id()

similarly other case also

Derived* d = new Derived(); //object type is Derived
d->id();

since id() method is not defined in the derived class it will call the base class id() only.

one more doubt is how you initialized the variable "id_" inside the class?

Upvotes: 0

underscore_d
underscore_d

Reputation: 6791

Why not simply give Base a constructor that sets id and have Derived call this constructor with its 'overridden' value? Boom: 'virtual data' according to the derived type.

Having said that, a virtual method might be more akin to encapsulation and provide opportunity for more elaborate behaviour later.

(Edit: I posted this as a comment and then converted it, by which point Richard had just beaten me to posting the answer. No copying has taken place!)

Upvotes: 1

Richard Hodges
Richard Hodges

Reputation: 69864

What is the correct way to implement the following?

Without meaning to sound difficult, it really depends on exactly what you want to achieve.

I'm going to make a guess that we're simply be asking an object what type it is, regardless of which interface we're calling on:

struct Base {
  virtual ~Base() = default;

  virtual const std::string id() const {
    return "Base";
  }
};

struct Derived : Base {
  virtual const std::string id() const override {
    return "Derived";
  }
};

Here's another way:

struct Base {
  virtual Base(std::string ident = "Base") 
  : _id(std::move(ident))
  {}

  virtual ~Base() = default;

  std::string& id() const {
    return _id;
  }

private:
  std::string _id;

};

struct Derived : Base {
  Derived() : Base("Derived") {}
};

And another, using value is interface, but note that this will disable the assignment operator

struct Base {
  virtual Base(std::string ident = "Base") 
  : id(std::move(ident))
  {}

  virtual ~Base() = default;

  const std::string id;

};

struct Derived : Base {
  Derived() : Base("Derived") {}
};

This list is by no means exhaustive.

Upvotes: 4

xtofl
xtofl

Reputation: 41509

Virtual functions exist, not virtual member variables.

What you do in your Derived class is define a new member variable id_ that hides it's parent. The id() function, however, is referring to the id_ defined in that context.

If you want to override the behavior, you should override the id() function:

class Derived: public Base {
    std::string id() const override { return "Derived"; }
};

Upvotes: 2

Related Questions