c++ - 关于不同类型继承的思考

标签 c++ inheritance c++11 vtable virtual-destructor

在查看以下简单代码时,如果我知道我们不是从基指针中删除,那么引入虚拟析构函数是否有意义?出于性能原因,我们似乎应该尽量避免 vtable 查找。我了解过早优化等,但这只是一个普遍的问题。我想知道您对以下方面的看法:

  • 如果我们不通过基指针删除项,则使用 protected 析构函数
  • 与引入单个虚拟方法相关的开销

此外,如果我的类只有析构函数作为虚方法,那么查找开销是否仅针对析构函数方法而其他方法不会招致损失,或者一旦引入 vptr 一切都会受到影响?我假设每个类内部都有一个额外的 vptr,但它只需要在析构函数上执行 vptr 查找。

class CardPlayer
{
  public:
    typedef std::vector<CardPlayer> CollectionType;

    explicit CardPlayer()=default;

    explicit CardPlayer(const Card::CollectionType& cards);
    explicit CardPlayer(Card::CollectionType&& cards);

    void receiveCard(const Card& card);

    bool discardCard(Card&& card);
    void foldCards();

    inline const Card::CollectionType& getCards()  { return cards_; }
    // virtual ~CardPlayer() = default;  // should we introduce vtable if not really needed?
  protected:
    ~CardPlayer()=default;
    Card::CollectionType cards_;
};
--------------------------------------------------------------------
#include "CardPlayer.h"
#include <functional>

class BlackJackPlayer : public CardPlayer
{
  public:
    typedef std::vector<BlackJackPlayer> CollectionType;
    typedef std::function<bool(const Card::CollectionType&)> hitFnType;

  BlackJackPlayer(hitFnType fn) : hitFn_(fn) {}

  bool wantHit() 
  {
    return hitFn_(getCards());
  }

  hitFnType hitFn_;
};

最佳答案

我会避免使用虚拟析构函数,因此会在您的案例中向该类添加一个 vtbl。您可以通过基类指针保护类不被删除,所以看起来,如果没有任何其他虚拟方法,这将是一种过早的悲观情绪:)

此外,每个实例(vtbl)多一个指针在大型项目中会增加。性能通常取决于内存访问,因此您应该使对象大小尽可能小,并且您的内存访问模式也应尽可能本地化。 vtbl 将位于不同的内存位置,在最坏的情况下,您要求处理器读取另一个缓存行只是为了删除一个对象。

回答您的另一个问题:只有虚拟方法通过 vtbl 路由,所有非虚拟调用都不会受到影响。

关于c++ - 关于不同类型继承的思考,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19210894/

相关文章:

c++ - 如何在 C++ 的 Qt Creator 中向 TableView 添加自定义对象?

c++ - 从 .txt 文件中读取 UNICODE 字符并将它们输出到控制台

python - 如何在python中继承 "Manager().list"?

java继承: distinguish between types of inherited classes

c++ - 为什么我不能构造一个绑定(bind)?

java - JVMT 异常监视器

function - 将继承的帧作为参数传递给过程

局部变量的 C++ lambda 词法闭包

c++ - 强制模板成员函数实例化

c++ - 使用二叉树实现字典