0

Could somebody help me understand what is going wrong with this type heirachy for validating input. Basically I have a superclass which can accept any string argument and a set of subclasses which can only accept certain inputs. I want to use inheritance to build an elegant way to check user input without duplicating code. Here is an example that has a few problems:


class Word {
    std::string word_;
public:
    Word(const std::string &word) {
        word_ = word;
        validateWord();
    }

    virtual std::vector<std::string> getValidWords(){
        return std::vector<std::string>({"All"});
    }

    void validateWord(){
        std::vector<std::string> valid_words = getValidWords();
        if (valid_words.size() == 1) {
            if (std::find(valid_words.begin(), valid_words.end(), "All") != valid_words.end()) {
                return;
            }
        }
        if (std::find(valid_words.begin(), valid_words.end(), word_) == valid_words.end()){
            throw std::invalid_argument("Word \"" + word_ + "\" not in valid words" );
        }
    }
};

class OneToThree : public Word {

public:
    explicit OneToThree(std::string word) : Word(word) {
    };

    std::vector<std::string> getValidWords() override {
        return std::vector<std::string>( {"One", "Two", "Three"});
    }
};


int main() {
    OneToThree var1("Three"); // should be fine
    OneToThree var2("randomWord"); // should fail
};

The debugger is telling me that the getValidWords() method from the subclasses are not being used in the validation function, but the one from the superclass.

enter image description here

Could anybody suggest the right way to do this?

CiaranWelsh
  • 7,014
  • 10
  • 53
  • 106
  • 3
    That's all because you're calling `getValidWords` from constructor. Changing to `OneToThree var(...); var.validateWord();` should work. Read this https://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors – fas May 25 '20 at 13:42
  • This is not a duplicate since the question has multiple problems. One is they are using the stack for the objects. – Bayleef May 25 '20 at 13:46
  • @BaileyKocin Why would using stack be wrong? – Yksisarvinen May 25 '20 at 13:51
  • 1
    You can't have runtime polymorphism that way. Which is what they were trying to do. So their whole approach to elegant inheritance is wrong. – Bayleef May 25 '20 at 13:52
  • Hence the keywords virtual and override. – Bayleef May 25 '20 at 13:53
  • @BaileyKocin [Sure you can](https://wandbox.org/permlink/5LJoxp8UqgA4QJQZ). Polymorphism doesn't have anything to do with memory location, but with the usage. Pointers and references work with every memory area. OP is not using polymorphism in their [mcve], but that's not their issue. – Yksisarvinen May 25 '20 at 14:01
  • The OP is trying to use virtual methods so one can assume runtime polymorphism is in the works. You do need pointers/references for this kind of polymorphism and the question asks "why are my virtual methods not being used in favor of the base". Two issues with that. One is you need pointers/references. Two, you can't call virtual methods in the constructors or destructor because the derived object won't be constructed yet or vice versa. Sure the OP can make a base class pointer to the objects they allocated on the stack but they didn't so they are misguided. – Bayleef May 25 '20 at 14:06
  • Sounds like I'm misguided. I'm experimenting with making my validate function static so I can call it from my subclasses in the constructor. – CiaranWelsh May 25 '20 at 14:11

0 Answers0