我无法想出一个适当的问题标题来描述问题.希望下面的细节清楚地解释了我的问题.
请考虑以下代码
#include <iostream>
template <typename Derived>
class Base
{
public :
void call ()
{
static_cast<Derived *>(this)->call_impl();
}
};
class D1 : public Base<D1>
{
public :
void call_impl ()
{
data_ = 100;
std::cout << data_ << std::endl;
}
private :
int data_;
};
class D2 : public Base<D1> // This is wrong by intension
{
public :
void call_impl ()
{
std::cout << data_ << std::endl;
}
private :
int data_;
};
int main ()
{
D2 …Run Code Online (Sandbox Code Playgroud) 我的一个朋友问我"如何使用CRTP替换多级继承中的多态".更准确地说,在这种情况下:
struct A {
void bar() {
// do something and then call foo (possibly) in the derived class:
foo();
}
// possibly non pure virtual
virtual void foo() const = 0;
}
struct B : A {
void foo() const override { /* do something */ }
}
struct C : B {
// possibly absent to not override B::foo().
void foo() const final { /* do something else */ }
}
Run Code Online (Sandbox Code Playgroud)
我和我的朋友都知道CRTP不是多态的替代品,但我们对可以使用这两种模式的情况感兴趣.(为了这个问题,我们对每种模式的利弊都不感兴趣.)
之前已经问过这个问题,但事实证明作者想要实现命名参数idiom …
我有一个普通的旧CRPT(请不要因访问限制而分心 - 问题与他们无关):
template<class Derived>
class Base {
void MethodToOverride()
{
// generic stuff here
}
void ProblematicMethod()
{
static_cast<Derived*>(this)->MethodToOverride();
}
};
Run Code Online (Sandbox Code Playgroud)
像往常一样打算像这样使用:
class ConcreteDerived : public Base<ConcreteDerived> {
void MethodToOverride()
{
//custom stuff here, then maybe
Base::MethodToOverride();
}
};
Run Code Online (Sandbox Code Playgroud)
现在static_cast困扰我了.我需要一个向下投射(不是向上投射),所以我必须使用一个明确的演员.在所有合理的情况下,强制转换都是有效的,因为当前对象确实是派生类.
但是如果我以某种方式改变层次结构并且演员现在变得无效呢?
我可以以某种方式强制执行编译时检查,在这种情况下显式向下转换有效吗?
如何避免
template <typename Derived>
struct base { int foo() { return static_cast<Derived*>(this)->bar(); } };
struct derived : base<derived> { int bar(); };
struct another_derived : base<derived> { int bar(); }; // error: wrong base
Run Code Online (Sandbox Code Playgroud)
派生类中没有额外的代码?
这个问题之前已经被问过两次 (尽管没有避免在派生类中添加额外代码的额外条件),并给出了推荐的答案
template <typename Derived>
struct base {
int foo() { return static_cast<Derived*>(this)->bar(); }
private:
~base() {}
friend Derived;
};
Run Code Online (Sandbox Code Playgroud)
然而,这不仅可以防止上述错误,而且还可以Base从 访问 的所有私有成员Derived。有没有替代方案可以避免这种情况?或者是否可以最终证明这是不可能的?
编辑
我实际上有一个更复杂的问题,除了通常的用法(如上所述)之外,还有
template<typename Derived>
struct intermediate : base<Derived>
{
int bar() { return static_cast<Derived*>(this)->ark(); …Run Code Online (Sandbox Code Playgroud)