为什么可以继承C ++中的接口

时间:2014-03-17 01:43:48

标签: c++ inheritance c++11

我有一个应用程序,我正在从C ++移植到Java。我发现有一段C ++代码非常奇怪。

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;

};

在原始C ++中,作者正在使他们的Arguments类继承自Map。这对我来说毫无意义。 Map是一个接口,意味着你不能从它继承,你只能实现它。这是可以在C ++中完成的,你不能用Java做的吗?

另外,我不明白你为什么要使用typedef。我从Wikipedia

中读到了这个定义
  

typedef是C和C ++编程语言中的关键字。 typedef的目的是   从更基本的机器类型[1]中形成复杂类型,并为此分配更简单的名称   组合。它们最常用于标准声明繁琐的情况,   可能令人困惑,或可能因实施而异:

但我不明白为什么作者会这样做。他们是否试图说他们想继承AnyData类并且ArgumentMap应该将Map作为其中一个字段?

4 个答案:

答案 0 :(得分:6)

  

这对我没有意义。地图是一个界面

在Java中,它是。在C ++中,它甚至不是一个类,它是一个类模板。 C ++没有类似于Java接口的概念,尽管你可以用虚拟继承实现类似的东西。

就集合类而言,C ++使用模板和泛型编程解决了Java通过接口和继承解决的问题。

C ++地图模板的实例是完全正常运行的类,其工作方式与Java TreeMap类似。您可以使用与从Java继承的相同方式继承它们,并且由于多重继承,您不仅限于单个类。

  

另外,我不明白为什么要使用typedef。

您使用typedef为类提供有意义的名称。除了缩短您的输入外,它还使您的程序更具可读性,并为您稍后重新定义typedef后面的课程提供了额外的灵活性。

注意: 继承标准容器的事实并不意味着您应该这样做。阅读this question的答案以获取更多信息。

答案 1 :(得分:4)

接口是特定于Java的语言构造。它们不存在于C ++中。在C ++中,您只有类。您可以拥有抽象类(具有未实现方法的类),最终您可以使用它们来发出接口。

答案 2 :(得分:2)

Map不是界面,它是模板。此外 - 作者并没有从map模板中获取他的类,但他从参数化模板中获得。没有班级的代码,人们只能猜测为什么他正在做这件事,以及他想要实现的目标。

请注意,从STL模板派生通常是一个坏主意(几乎没有特殊情况),并且通常使模板成为您的类的成员要好得多。模板没有virtual个成员,因此 - 在推导时没有真正改变行为的方式(在许多情况下这是真正的继承点)。

关于typedef的一点:当你使用类似的typedef时,你的代码将来会更容易改变。当您(出于任何原因)决定要实施自己的string课程时,您只需要更改此文件中的第一行(从typedef std::string ArgName;更改为typedef myNewStringClass ArgName;),而不是更改ArgName发生的所有地方的代码。

答案 3 :(得分:2)

C ++有多重继承,没有“接口”。你当然可以继承任何一个班级。而且C ++有模板,Java中完全没有。模板允许您使编译器编写专门定制的函数或类。