【问题标题】:How to declare a class explicity abstract?如何声明一个类显式抽象?
【发布时间】:2013-06-19 15:52:41
【问题描述】:

我正在查看以下内容:

http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr142.htm

它说 C++ 中的抽象类包含一个纯虚函数。但是,这并不意味着创建一个抽象类我所做的只是插入一个纯虚函数?难道我不能有一个具体的类,它不为一个特定的函数提供实现,因此使其抽象,强制派生类提供实现吗?这不会使类抽象吗?

那么如何区分“这是一个抽象类”和“这是一个具有一个纯虚函数的具体类”?

【问题讨论】:

  • 问题有点不清楚/令人困惑。您非常清楚地表明您已经理解抽象类必须包含纯虚函数。这就是要求。如果您没有纯虚函数,则您的类不是抽象的。所以你问这是否正确?
  • 是的,至少有一个纯虚函数会使类抽象。 Reading this 可能会对您有所帮助。
  • @kfsone 你是说具体类不能包含纯虚函数?
  • @BobBlogge 将虚函数设置为 0,使其成为纯虚函数。
  • @user997112 我的意思是——正如你已经说过的——向一个类添加一个纯虚函数会使该类成为一个抽象类。一旦你为所有 pvf 提供了实现,你的类就是具体的。

标签: c++ inheritance polymorphism virtual abstract


【解决方案1】:

当一个类有一个或多个纯虚函数时,它就是抽象的。如果您编写一个(基)类,它实现了所有功能,因此可以实例化,但它错过了一个重要功能,那么这只是您的类的错误设计。 在这种情况下,您的基类将不完整,应添加纯虚拟未实现函数,使其成为抽象类。

如果你有一个派生类,它派生自一个抽象类,并且没有实现基类的所有功能,那么它又是抽象的。在这种情况下,它本身不需要纯虚函数,因为它是通过继承抽象的。

C++ 中没有 abstract 关键字,就像在 Java 中一样,表示一个类是抽象的。

【讨论】:

    【解决方案2】:

    如上所述,根据定义,C++ 中的抽象类是具有至少一个纯虚函数的类。类是抽象的意味着你不能创建它的实例(只有从它派生的“具体”类),这可以保护你不调用“不存在”的纯虚函数(尽管从技术上讲,你仍然可以从基类构造函数中调用它们/destructor 并导致严重的运行时崩溃)。

    C++ 中没有明确的“接口”类型的类,因此您可以随意为任何类中的某些函数提供实现,无论该类是否由于某些其他函数是纯虚函数而已经是抽象的。

    在旁注中,我仍然想指出一种使您的类抽象而不实际使任何“真实”方法成为纯虚拟的方法。将类 destructor 设为纯虚拟就足够了(请注意,任何多态类的析构函数通常都是虚拟的,这通常是个好主意)。这里的一个小问题是,在这种特殊情况下(仅适用于析构函数),您仍然必须为其提供一个实现,以使链接器满意。它可能看起来像这样:

    class A // abstract class
    {
    public:
        virtual ~A() = 0 {} // destructor is pure virtual, but still needs a body
    };
    
    class B : public A {}; // concrete class deriving from an abstract class
    

    另请注意,在这种特殊情况下,B 类不必显式实现其自己的析构函数以变得具体,因此,如果您也希望它是抽象的,则必须再次重复相同的技巧(或者在 B) 中添加一些其他纯虚方法。

    【讨论】:

    • 有趣的技巧 :) 但我有一个后续问题:将构造函数设为私有还有一个技巧。这也使得类不可能被“外部世界”实例化(尽管它仍然可以被类的方法或类的朋友在内部实例化)。这两种技术有何不同,在哪些特定情况下哪种更好?
    • @SasQ 如果你为一个类标记所有构造函数private,那么将其抽象化就没有任何意义:没有派生类能够构造自己,因为它必须调用首先是基本构造函数之一。当然,您可以改用protected。私有构造函数也有正当的理由,尽管它们与抽象类无关。单例通常将它们与私有析构函数一起使用。它们还有助于确保您的类对象始终是动态创建的,并且永远不会在堆栈上:只需提供一个内部带有 new 的公共静态方法。
    • 你说得对,我应该说“非公开”而不是“私人”,因为这就是我的意思。 protected 包含在此类别中,因此派生类可以调用此类构造函数。
    • 关于使构造函数private 以防止在堆栈上构造它们:我认为这行不通。它们仍然可以在它自己的类的所有静态成员函数内的堆栈上创建,也可以由它的朋友创建。只有外面的世界不能。
    • 对,我就是这个意思。 :) 任何类肯定都有权对自己做任何事情,这就是所谓的“实现细节”。但是以防止类用户错误的方式为外部世界设计界面仍然非常有帮助。当您设计一个新类时,您可能已经知道在堆栈上创建它是否安全,并相应地编写代码。然而,这个类的其他一些用户(或者你自己,在长时间的休息之后)可能不知道......直到他们看到私有构造函数 + 静态创建方法,这使得意图显而易见并强制合规。
    猜你喜欢
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    • 2021-06-10
    • 2016-05-10
    相关资源
    最近更新 更多