gpt4 book ai didi

c++ - 为什么 CRTP 实现和接口(interface)方法的命名不同?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:21:56 24 4
gpt4 key购买 nike

无论我在哪里阅读有关 CRTP 的文章,实际上在我编写的代码中,CTRP 类层次结构都类似于以下内容:

template< class T >
class Base
{

public:

int foo_interface()
{
return static_cast< T* >(this)->foo_implementation();
}

};

class Derived : public Base< Derived >
{

friend class Base< Derived >;

int foo_implementation()
{
return 5;
}

};

也就是接口(interface)名称和实现方法不同。现在,我通常不希望实现方法从外部可见,这需要上面的 friend 声明,并且在多级层次结构中证明是一个主要的问题(即使使用描述的技巧 here )。

现在,我想到了以下内容:

// Base class
template< class T >
class A
{

public:

int foo()
{
std::cout << "I'm in A's foo!\n";
return static_cast< T * >(this)->foo();
}

};

// Deriving class
class B : public A< B >
{

public:

int foo()
{
std::cout << "I'm in B's foo!\n";
return 5;
}

};

// Deriving class with a nasty surprise...
class C: public A< C >
{

public:

// ...crap, no foo to be found!

int bar()
{
std::cout << "I'm in C's bar!\n";
return 12;
}

};

template< class T >
int call_foo(A< T > & t)
{
return t.foo();
}

B b;
C c;

现在,call_foo(b) 就像我期望的那样工作,调用 B 的 foo() 实现。同样,call_foo(c) 也按预期工作(因为它没有……由于显而易见的原因而陷入无限循环)。我看到的一个缺点是,如果我忘记在派生类中实现一个方法(或者拼写错误,忘记将其限定为 const,等等......),我会得到一个无限循环,所以它可能会产生那种错误有点难找,因为它们在编译时没有被捕获。但除此之外,它几乎和普通虚函数一样简单,而且我不必为隐藏实现方法而苦恼。它看起来简单而优雅,但似乎没有人在使用它……我的问题是,有什么问题?为什么不使用这种方法?隐藏实现方法只是没什么大不了的吗?或者当我在实际项目中尝试这种方法时,是否有某种不可估量的邪恶力量潜伏在那里准备吞噬我的灵魂?

最佳答案

除了您提到的同名接口(interface)函数及其实现的问题外,CRTP 背后没有潜伏的“邪恶力量”,但在我看来,这有点像“自找麻烦”。

至于“为什么不使用这种方法?”这个问题,我认为情况并非如此。这种方法在需要时被广泛使用;但没有一种设计模式始终 有意义。在某些特定的设计情况下,每一种都会派上用场,CRTP 也不异常(exception)。

当您有几个不相关类支持公共(public)接口(interface)但略微实现它时,CRTP 最有用strong>(不完全)不同。如果我以粗体显示的这些词中任何没有描述您的设计用例,则 CRTP 可能毫无意义:

  • “几个”:如果您只有一个这样的类而不是很多,为什么要将其接口(interface)分解为一个父类(super class)?它只是引入了一些多余的命名约定;
  • “不相关”:如果您的类是相关的,这意味着它们派生自公共(public)基类,因为需要运行时多态性(这种情况很常见,比如您想要异构对象集合),那么将公共(public)接口(interface)纳入该基类通常变得很自然;
  • “通用”:如果您的类不共享一个相当广泛的通用接口(interface),那么基类就没有太多可考虑的因素。例如,如果您的所有类 有一个共同的size() 方法,创建一个基类只是为了保存该方法可能是一个无用的细粒度分解;
  • “稍微”:如果您的接口(interface)以完全不同的方式实现,意味着没有通用的实现,那么它就不会创建一个简单地将所有函数调用转发给子类的基类是有意义的。做什么的?

但是,当您的设计情况满足上述四个属性的所有时,那么您肯定有 CRTP 的用例:没有虚函数开销,编译器可以完全优化您的代码,您可以清楚地分离接口(interface)和实现,通过捕获通用实现逻辑来实现最小冗余,等等。

但是,您可能会意识到这种情况并不常见。希望这能回答您的问题。

关于c++ - 为什么 CRTP 实现和接口(interface)方法的命名不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14625801/

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