Override initial value of a member variable of base class

二次信任 提交于 2021-02-15 05:16:41

问题


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;
}

回答1:


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.




回答2:


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"; }
};



回答3:


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!)




回答4:


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?



来源:https://stackoverflow.com/questions/34592361/override-initial-value-of-a-member-variable-of-base-class

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!