gpt4 book ai didi

c++ - 为什么为通用基类型编写通用代码是 C++ 中模板的糟糕替代方案?

转载 作者:行者123 更新时间:2023-11-30 00:50:14 26 4
gpt4 key购买 nike

在阅读一本关于 C++ 模板的非常好的书时,我遇到了一个我不理解的关于替代模板的解释:

These are bad alternatives to templates in C++

  1. You can write general code for a common base type such as Object or void*.

Reason : If you write general code for a common base class you lose the benefit of type checking. In addition, classes may be required to be derived from special base classes, which makes it more difficult to maintain your code.

谁能用代码示例解释一下?

最佳答案

糟糕的不是通用基类型的概念。这是对“对象类”的使用,一切都必须派生自,或者更糟的是,编写采用 void* 的代码,然后假设指针指向什么,将类型转换为指向的指针一些其他类型并希望最好。容器就是最好的例子。

实现容器方法的正确方法是使用模板。例如:

template<typename T> void List<T>::append(const T& obj);

对象等级

Object 基类的情况下,这意味着您放入容器中的任何内容都必须派生自 Object,因为所有容器方法都使用 Object* 作为所述容器中的数据。所以你得到这样的方法:

void List::append(Object* obj);

这里有两件坏事:首先,无论您走到哪里,Object 类都必须与您的容器一起拖来拖去。其次,它是一个非常通用的名称,可能会与其他库中的 Object 类冲突。

此外,您的容器永远不能包含不是 Object 直接派生的类型,包括像 int 这样的原始类型和像 std::string< 这样的标准类型。您必须将这些类型“包装”在 Object 子类中,然后您必须花时间编写代码以从这些包装对象中提取值,等等。后面很痛苦你不需要。

无效*

所以你可能认为你可以使用通用指针 void* 代替:

void List::append(void* obj);

但是当你这样做时,容器可能需要做很多它不能做的事情,因为它不知道 void* 指向什么:

  • 它不能复制数据对象。
  • 它不能比较数据对象。
  • 不能删除数据对象。

等等。 (您可以使用虚方法在 Object* 情况下避免这些问题,例如声明如下内容:

virtual ~Object() {}
virtual Object* clone() const;
virtual int cmp(const Object* rhs) const;

在您的 Object 基类中,这些方法必须所有 子类覆盖。但是现在你的 Object 类不是很轻量级。)

在这两种情况下,您最好为容器的数据类型使用模板化类型。如果您担心代码膨胀并且容器中的代码不关心数据类型(因为它不关心数据,例如在计算包含的元素时),您可以将该代码放在基类中并让您的模板化容器类从中派生。但大多数时候没有人真正关心这种“膨胀”,因为它比您的可用内存小得多。

放弃类型检查

If you write general code for a common base class you lose the benefit of type checking.

由于您已对 Object*void* 进行了类型转换,因此类型检查在大多数情况下都被排除在外了。 (注意:这有点过时了,因为在某些情况下,您可以使用运行时类型识别 (RTTI) 和 dynamic_cast 操作来执行事后类型检查,以确保您从容器是您期望的类型。但是上述所有限制仍然适用,因为容器仍然不知道它包含什么。)

关于c++ - 为什么为通用基类型编写通用代码是 C++ 中模板的糟糕替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25696133/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com