Абстрактный член класса не может получить доступ к значению, установленному в производных классах - PullRequest
1 голос
/ 16 января 2012

У меня есть следующий абстрактный класс

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

И ряд производных классов, таких как этот, которые его реализуют

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

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

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

Проблема, с которой я столкнулся, заключается в load_conf() где по какой-то причине name считается пустым, что выдает ошибку, даже если конфигурация в порядке.load_conf() вызывается из run(), который реализуется каждым производным классом.

Я пытался сделать name защищенным и общедоступным, но ни один из них, похоже, не имеет никакого значения.В идеале я хотел бы объявить name только в абстрактном классе (как защищенный) и не должен повторять объявление в каждом производном классе, но когда я пытаюсь это сделать, он не скомпилируется.Я также пытался использовать this->name, но он также пуст, и удаление const также не имеет значения.

У меня такое ощущение, что это проблема с областью видимости, но чего мне не хватает?

Ответы [ 3 ]

6 голосов
/ 16 января 2012

Объявите конструктор в вашем базовом классе, который принимает один аргумент, значение для инициализации name и передачи его в производные ctors.

, вот пример:

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

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

Что-то вроде следующего должно заменить вышесказанное ...

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...
};
1 голос
/ 16 января 2012

У вас уже есть переменная с именем name в Базовом классе Language Когда вы ссылаетесь на name внутри load_conf(), компилятор ссылается на переменную Базового класса name, а не на производную переменную класса name,

Простое решение состоит в том, чтобы иметь отдельные имена для двух переменных или
Сделать name в Базовом классе как protected, чтобы каждый производный класс мог ссылаться на эту переменную.

0 голосов
/ 16 января 2012

в вашем class Python вы переопределяете поле name, на которое не ссылается load_conf.

Создайте name в вашем Language классе protected и удалите однов его подклассах, и он должен работать хорошо.

...