虚拟继承和静态继承——C++中的混合

2023-11-26

如果你有这样的事情:

#include <iostream>

template<typename T> class A
{
public:
    void func()
    {
        T::func();
    }
};

class B : public A<B>
{
public:
    virtual void func()
    {
        std::cout << "into func";
    }
};

class C : public B
{
};

int main()
{
  C c;
  c.func();

  return 0;
}

func() 是动态调度的吗?
如何实现类 A,以便如果 B 有虚拟覆盖,则动态分派它,但如果 B 没有虚拟覆盖,则静态分派?

编辑:我的代码没有编译?对不起大家。我现在有点病了我的新代码也无法编译,但这是问题的一部分。另外,这个问题是针对我的,而不是常见问题解答。

#include <iostream>

template<typename T> class A
{
public:
    void func()
    {
        T::func();
    }
};

class B : public A<B>
{
public:
    virtual void func()
    {
        std::cout << "in B::func()\n";
    }
};

class C : public B
{
public:
    virtual void func() {
        std::cout << "in C::func()\n";
    }
};
class D : public A<D> {
    void func() {
        std::cout << "in D::func()\n";
    }
};
class E : public D {
    void func() {
        std::cout << "in E::func()\n";
    }
};

int main()
{
  C c;
  c.func();
  A<B>& ref = c;
  ref.func(); // Invokes dynamic lookup, as B declared itself virtual
  A<D>* ptr = new E;
  ptr->func(); // Calls D::func statically as D did not declare itself virtual
  std::cin.get();

  return 0;
}

visual studio 2010\projects\temp\temp\main.cpp(8): error C2352: 'B::func' : illegal call of non-static member function
      visual studio 2010\projects\temp\temp\main.cpp(15) : see declaration of 'B::func'
      visual studio 2010\projects\temp\temp\main.cpp(7) : while compiling class template member function 'void A<T>::func(void)'
      with
      [
          T=B
      ]
      visual studio 2010\projects\temp\temp\main.cpp(13) : see reference to class template instantiation 'A<T>' being compiled
      with
      [
          T=B
      ]

我不确定我明白你在问什么,但看来你错过了基本的 CRTP 演员阵容:

template<class T>
struct A {
  void func() {
    T& self = *static_cast<T*>(this);  // CRTP cast
    self.func();
  }
};

struct V : A<V> {  // B for the case of virtual func
  virtual void func() {
    std::cout << "V::func\n";
  }
};

struct NV : A<NV> {  // B for the case of non-virtual func
  void func() {
    std::cout << "NV::func\n";
  }
};

如果 T 没有声明自己的 func,这将是无限递归,因为 self.func 会找到 A::func。即使 T 的派生类(例如下面的 DV)声明了自己的 func 但 T 没有声明,这也是如此。

使用不同的最终覆盖程序进行测试,以显示调度工作如广告所示:

struct DV : V {
  virtual void func() {
    std::cout << "DV::func\n";
  }
};
struct DNV : NV {
  void func() {
    std::cout << "DNV::func\n";
  }
};

template<class B>
void call(A<B>& a) {
  a.func();  // always calls A<T>::func
}

int main() {
  DV dv;
  call(dv);   // uses virtual dispatch, finds DV::func
  DNV dnv;
  call(dnv);  // no virtual dispatch, finds NV::func

  return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

虚拟继承和静态继承——C++中的混合 的相关文章

随机推荐