何时使用抽象类是有意义的?

4

我正在从C语言转向C++,当然也包括面向对象编程(OOP),这比我预期的更加困难。难点不在于理解类和继承的核心机制,而在于如何使用它们。我已经阅读了有关设计模式的书籍,但它们只展示了技术,模糊地描述了为什么应该使用这些技术。我真的很难找到抽象类的用途。例如下面的代码:

class baseClass {
public:
    virtual void func1() = 0;
    virtual void func2() = 0;
};
class inhClass1 : baseClass {
public:
    void func1();
    void func2();
};
class inhClass2 : baseClass{
public:
    void func1();
    void func2();
};
int main() {}

我经常在设计书籍中看到这样设置抽象类的例子。我知道通过这种配置,继承类可以访问基类的公共成员。我知道虚函数是继承类的占位符。问题是我仍然不明白这有什么用处。我试图将其与函数重载进行比较,但我并没有看到实际应用场景。
我真正想要的是有人给出最简单的例子来说明抽象类为什么实际上很有用,并且是解决某些情况下的最佳方案。别误会,我并不是说没有好答案。我只是不明白如何正确使用它们。

1
你理解接口的概念吗? - Carcigenicate
不完全是。我已经了解过它们,但我真的不理解它们。据我所知,基类将是一个接口。至少在这个例子中是这样的。 - mreff555
1
@mreff555 ABCs可以在C++中用于创建接口,因为C++没有像Java那样的显式接口。长话短说,如果一个类实现了一个接口,你就知道它具有某种功能。ABCs允许您拥有一个包含可以由实现者共享的代码的接口。 - Carcigenicate
好的,我修改了我的代码,所以现在它是一个正式的抽象类。我想我的原始问题的延伸将是,为什么这种格式的代码比没有抽象类的两个具体类更有效率。即使有十几个或更多的这些继承类,我也不明白抽象化如何改善情况。 - mreff555
谢谢,我正在阅读这篇文章。顺便说一下,duffymo。由于代码如上所示,GNU编译器将其称为抽象类。还需要什么额外的要求?纯虚构造函数/析构函数吗? - mreff555
显示剩余7条评论
3个回答

7
抽象类和接口都允许您定义子类需要实现的方法签名,包括名称、参数、异常和返回类型。
如果存在合理的默认实现,抽象类可以提供默认实现。这意味着子类不必实现此方法;如果愿意,它们可以使用默认实现。
接口没有这样的选项。实现接口的类必须实现其所有方法。
在Java中,区分很明显,因为语言包括关键字"interface"。
C++接口是具有所有虚拟方法和一个纯虚拟析构函数的类。
当您想将接口与实现解耦时,使用抽象类和接口。当您知道将有多个实现可供选择或者正在编写允许客户端插入其自己的实现的框架时,它们非常有用。接口提供了客户端应遵循的契约。

1
请注意,这是一个关于C++的问题,不是Java的问题。 - Code-Apprentice
我知道。接口的概念超越了Java和C++。在C++中,它将是一个具有所有虚方法和纯虚析构函数的类。 - duffymo
1
是的,只要理解为一般概念而不是关键字就可以了。我只是想澄清一下。 - Code-Apprentice

4

抽象类的一个用途是能够在最小程度更改代码的情况下轻松切换不同的具体实现。这可以通过声明一个基类类型的引用变量来实现。派生类的唯一提及是在创建时。所有其他代码都使用基类引用。


编码时使用接口,而不是特定的实现。 - Carcigenicate

0

抽象类用于提供某个概念的抽象表示,隐藏细节,以实现该概念。

例如,假设我想要实现文件系统接口:

在抽象层面上,我能想到什么?

class FileSystemInterface
{
    virtual void openFile();
    virtual void closeFile();
    virtual void readFile();
    virtual void writeFile();
};

目前我并没有考虑到它们在Windows或Linux中如何处理,而是专注于一些抽象的想法。


这似乎很有用,如果我的问题显得无知,我很抱歉,但我从c99和函数重载开始。你仍然需要编写其他类。编写额外的抽象类有什么好处? - mreff555
主要的好处是你将会编写一个接口而不是实现。因此,以后你可以随意更改实现方式,而不会影响到你的客户端。 - ravi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接