简体   繁体   中英

Abstract class member can't access value set in derived classes

I have the following abstract class

class Language {
    const std::string name ;

    protected:
    std::string cmd, home ;
    Config::Section cfg ;

    bool load_conf() {
        home = env("HOME") ;

        // DEBUG
        std::cout << home << std::endl ;
        std::cout << name << std::endl ;

        if (!cfg.load(home + "/.cr", name)) {
            std::cerr << "cr: No configuration found for this language." << std::endl ;
            return false ;
        }

        return true ;
    }

    public:        
    virtual bool handles(const std::string) = 0 ;
    virtual int run(std::string) = 0 ;
} ;

And a number of derived classes, like this, which implement it

class Python : public Language {
    const std::string name ;

    public:
    Python() : name("python") {}

    bool handles(const std::string) ;
    int run(std::string) ;
};

The problem I'm having is in load_conf() where for some reason name is reported to be empty, which makes it spit out an error even though the configuration is fine. load_conf() is called from run() which is implemented by each derived class.

I've tried making name protected and public, but neither seems to make any difference. Ideally I'd like to only declare name in the abstract class (as protected) and not have to repeat the declaration in each derived class, but when I try that it won't compile. I've also tried using this->name but that's also empty, and removing the const also makes no difference.

I get the feeling it's a scoping issue, but what am I missing?

Declare a constructor in your base class which accepts a single argument, the value to intialize name to and pass that in the derived ctors.

here is an example:

class Language {
    const std::string name ;
};

class Python : public Language {
    const std::string name ; // <-- this is different, and frankly redundant
};

Something like the following should replace the above...

class Language {
    const std::string name ;
    Language(std::string some_name) : name(some_name) {}  // <-- set the name
};

class Python : public Language {
    Python() : Language("python") {} // construct the base with the name...
};

You already have a variable with named name in the Base class Language When you refer to name inside load_conf() the compiler refers to the Base class name variable and not derived class name variable.

Simple solution is to have separate names for the two variables or
Make the name in Base class as protected so each derived class can refer to this variable.

in your class Python you are overriding the field name which is not the one referenced by load_conf .

Make name in your Language class protected and remove the one in its subclasses and it should work well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM