1

I have an application that I'm porting from C++ to Java. There is a section C++ code that I find really strange.

typedef std::string ArgName;
typedef std::map< ArgName, AnyData > ArgumentMap;

class Arguments : public ArgumentMap
{
    public:
    // Very important note: When read finds a numeric/set argument,
    // it sets anyData.kind to Int. But STILL, it fills anyData.dString,
    // just in case. So if the ArgumentMap was built by Arguments::read,
    // the dString fields are all filled.
    bool read( int argc, char **argv );

    // remains is filled with the arguments not starting with '-'.
    bool read( int argc, char **argv, std::vector<const char*>& remains );

    // const if fails, erases arg if succeeds.
    bool getNumericParam( const ArgName& name, int& num );

    // sw is true if the switch is present. The function
    // returns false if the argument value is not empty.
    bool getSwitch( const ArgName& name, bool& sw );

    bool getSwitchConst( const ArgName& name, bool& sw ) const;

    // Returns true if the switch is present. Throws an error message if
    // if the argument value is not empty.
    bool getSwitchCompact( const ArgName& name );

    void checkEmptyArgs() const;

};

It looks like in there original C++ the author is making their Arguments class inherit from a Map. This makes no sense to me. Map is an interface which means you can't inherit from it, you can only implement it. Is this something that can be done in C++ that you can't do in Java?

Also, I don't understand why you would use a typedef. I read the definition from Wikipedia

typedef is a keyword in the C and C++ programming languages. The purpose of typedef is to form complex types from more-basic machine types[1] and assign simpler names to such combinations. They are most often used when a standard declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another

But I don't understand why the author would do that here. Are they trying to say that they want to inherit from the class AnyData and that ArgumentMap should have a Map as one of its fields?

TobiMcNamobi
  • 4,687
  • 3
  • 33
  • 52
j.jerrod.taylor
  • 1,120
  • 1
  • 13
  • 33
  • On one hand, nicely written question. On the other, it would take less than half the time of writing this to check some [c++ reference](http://en.cppreference.com/w/cpp/container/map) for details on `std::map`. – Xarn Mar 17 '14 at 08:58
  • @Xam I tried looking for something before I posted to Stackoverflow. The problem was that I was looking for the wrong thing. I'd forgotten that there are no interfaces in C++. I tried googling things about C++ and inheritance because the way I was thinking about it, this was a weird inheritance issue. It **never** would have occurred to me to look up class templates, virtual inheritance, etc. It might seem obvious for you since you know C++ well, but since I know Java better I was literally scratching my head going WTF!?!? – j.jerrod.taylor Mar 17 '14 at 14:58

4 Answers4

6

This makes no sense to me. Map is an interface

In Java, it is. In C++, it's not even a class, it is a class template. C++ does not have a concept similar to Java's interfaces, although you can implement something similar with virtual inheritance.

As far as the collection classes are concerned, C++ solved with templates and generic programming what Java solved with interfaces and inheritance.

Instances of C++ map template are fully functioning classes that work similarly to Java's TreeMap. You can inherit them in the same way that you inherit from classes in Java, and because of multiple inheritance, you are not limited to a single class.

Also, I don't understand why you would use a typedef.

You use typedef to give classes meaningful names. In addition to shortening your typing, it makes your program more readable, and gives you additional flexibility at redefining the class behind the typedef later on.

Note: the fact that you can inherit from standard containers does not mean that you should do it. Read answers to this question for more information.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • So Map is a class in C++ that's why the author can inherit from it? I think I'll do better just making this a field of the Arguments class in the Java that I'm writing. – j.jerrod.taylor Mar 17 '14 at 01:58
  • How is a pure virtual abstract class (except with a trivial virtual destructor) inherited from virtually distict from a Java interface? – Yakk - Adam Nevraumont Mar 17 '14 at 02:50
  • @Yakk The first thing that comes to my mind is if you inherit from two such "interfaces", and both of them have a method with the same signature that they did not inherit from a common ancestor, the inheriting class would need to implement both methods separately. In Java, a single implementation would suffice. – Sergey Kalinichenko Mar 17 '14 at 02:57
  • @dasblinkenlight `struct A{virtual int f()=0;};struct B{virtual int f()=0;};struct C:virtual A,virtual B{int f(){return 3;};};` impelements both? -- but not if you implement `f` "above" where you mix in one of `A` or `B` , that different in Java? – Yakk - Adam Nevraumont Mar 17 '14 at 03:42
  • @NoSenseEtAl The link has nothing whatsoever to do with my answer. You did not confuse my answer for a *recommendation* to inherit from standard containers, did you? The fact that you *can* inherit standard containers does not mean that you *should* inherit from them. – Sergey Kalinichenko Mar 17 '14 at 12:16
  • Java doesnt suffer from virtual dtor problem so saying you can inherit like in Java is wrong, ofc IMAO – NoSenseEtAl Mar 17 '14 at 12:24
  • @NoSenseEtAl I am not aware of C++ "suffering from virtual destructor problem". Of course, like most language features, destructors are open to some misuse, but they do not present a problem in themselves. – Sergey Kalinichenko Mar 17 '14 at 12:34
4

Interfaces are a language construct specific to Java. They do not exist in C++. In C++ you only have classes. You can have abstract classes (classes with unimplemented methods), and eventually you can use them to enunciate interfaces.

b2Wc0EKKOvLPn
  • 2,054
  • 13
  • 15
2

Map isn't an interface, it's a template. Moreover - the author doesn't derive his class from the map template as a whole, but he derives from a parametrized template. Without the code of the class, one can only guess why he's doing it, and what he wants to achieve.

Note that deriving from STL templates is a bad idea in general (with few exceptional cases) and usually it's much better to make the template a member of your class. Templates don't have virtual members and thus - there's no real way to change their behaviour when deriving (and that's the real point of inheritance in many cases).

And a bit about the typedefs: when you use a typedef like that, you make your code a bit easier to change in the future. When you (For any reason) decide that you want to implement your own string class, you only need to change the first line in this file (from typedef std::string ArgName; to typedef myNewStringClass ArgName;), instead of changing the code in all the places where ArgName occurs.

Paweł Stawarz
  • 3,952
  • 2
  • 17
  • 26
  • I would question your statement "STL templates aren't ment to be base classes in the first place". How do you reconcile that with e.g. a `protected` member in `std::stack`? – Cheers and hth. - Alf Mar 17 '14 at 01:55
  • @Cheersandhth.-Alf maybe that statement was a bit to harsh, and a bit biased. Let me edit that in a way to reflect that. – Paweł Stawarz Mar 17 '14 at 01:58
  • I added the code from the class. That was another thing that I found really confusing. It is just the method declarations and no actual implementation. I know that you can do this in C++, but I haven't been able to find the actual implementation in my code yet. – j.jerrod.taylor Mar 17 '14 at 02:03
  • if the destructor isn't virtual that's a very strong hint that it is not meant to be inherited from – paulm Mar 17 '14 at 02:03
2

C++ has multiple inheritance, there are no "interfaces". You can certainly inherit from any class. And C++ has templates, something completely absent in Java. Templates allow you to make the compiler write specially tailored functions or classes.

vonbrand
  • 11,412
  • 8
  • 32
  • 52