1

I have an interface class with a default implementation and an inheriting class with its header and cpp file.

List.h

class List {
public:
    virtual int search(const string searchCharacters, bool caseSensitive){return 0;}
}

MyList.h

class MyList : public List {

}

MyList.cpp

int MyList::search(const string searchCharacters, bool caseSensitive)
{
    // Implementation code
}

Now, I'm getting member function not declared in 'MyList' for some reason. I have a Java background and still have some issues adjusting to C++ way of things. Why isn't the definition being carried through the MyList header file?

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
Jan
  • 83
  • 8
  • 5
    This is not valid C++ code. You need to learn the language before you start coding with it. You do not have an Interface class here, and none of your functions are virtual. You also need to declare all functions, right now `MyList::search` is not declared. – SergeyA Nov 06 '15 at 15:57
  • Well where exactly is your `virtual`????? – barak manos Nov 06 '15 at 16:00
  • You haven't given a "minimal, complete and verifiable" example. Have a look at http://stackoverflow.com/help/mcve. – Mike P Nov 06 '15 at 16:00
  • @Mike Well, it's hard to provide a complete example for an issue that obviously arises from incomplete code, isn't it? – decltype_auto Nov 06 '15 at 16:06
  • @decltype_auto; neither can we reproduce the compiler error the OP reports, using the code provided?! – Mike P Nov 06 '15 at 16:10
  • 1
    @MikeP [this](http://coliru.stacked-crooked.com/a/d263655bbba0e3a9) compiles with your c++? I doubt that. – decltype_auto Nov 06 '15 at 16:13

2 Answers2

4

You need to declare the function in the derived class:

class MyList : public List
{
public:
    int search(const string searchCharacters, bool caseSensitive);
}

Note that the declaration and defination are not the same thing in C++. In this case, you can't define the member function in cpp file without declaration. If you don't declare (and define) it, then derived class will inherit it from the base class, including the defination.

And if you want it to be polymorphic you need to make it virtual in the base class, and it's better to make the destructor virtual at the same time if you'll use them by base class's pointer:

class List
{
public:
    virtual int search(const string searchCharacters, bool caseSensitive){return 0;}
    virtual ~List() {}
}

As @SergeyA pointed, you can also make it a pure virtual function to make it be similar with java-style interface more. In this case you don't need to provide defination for it. (You still could provide one)

class List
{
public:
    virtual int search(const string searchCharacters, bool caseSensitive) = 0;
    virtual ~List() {}
}

At last, C++ and Java are totally different. If you want to master C++, try to think in C++ style.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 2
    I'd also add the `override` keyword to make sure you've got the the correct signature. – Mike Vine Nov 06 '15 at 16:06
  • 1
    Better way would be to make it pure virtual. – SergeyA Nov 06 '15 at 16:22
  • I can't make pure virtual because of legacy issues, every inheriting class would be forced to implement the function (and some don't even need it anyway). Thanks for the suggestion thought! – Jan Nov 06 '15 at 16:35
  • @Jan "every inheriting class would be forced to implement the function" Then your inheriting classes aren't really implementing the interface, and you need to break down the interface further or rethink the design. Otherwise you're breaking the [LSP](http://stackoverflow.com/questions/56860/what-is-the-liskov-substitution-principle), unless it makes sense for the default implementation to do nothing without any ill effects. – Kuba hasn't forgotten Monica Nov 06 '15 at 17:06
  • @KubaOber They implement some of the changes but due to poor legacy design decisions in my project the architecture is all over the place. And if I now start the same "hacks" again by creating yet another sub interface this it not going to get better anytime soon. – Jan Nov 07 '15 at 18:19
1

Unlike Java non-private member methods which are always virtual, a C++ member-function is not virtual unless you have explicitly declared it virtual in the base class:

class List {
public:
    virtual int search(const string searchCharacters, bool caseSensitive) {
        return 0;
    }
};

If you want to supply an implementation of an override in your cpp file, you need to also supply a declaration of the member-function that you are overriding in your header:

class MyList : public List {
public:
    int search(const string searchCharacters, bool caseSensitive) override;
};

Note the optional override specifier at the end of the declaration.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523