考虑以下代码:
#include <iostream>
#include <string>
class Base {
protected:
virtual std::string addMoreDetail (std::string&) const = 0;
};
template <int...> class Derived;
template <>
class Derived<0, 0> : private Base {
private:
bool b;
protected:
virtual std::string description() const {return "Whatever1";}
std::string finalize (std::string& str) const {return b ? addMoreDetail(str) : str;}
};
template <>
class Derived<1, 0> : private Base {
protected:
virtual std::string description() const {return "Whatever2";}
std::string finalize (std::string& str) const {return addMoreDetail(str);}
};
template <int N>
class Derived<N, 0, 0> : public Derived<N, 0> {
public:
virtual std::string description() const override {
std::string str = Derived<N, 0>::description(); return this->finalize(str);
// Can this be moved up somehow?
}
private:
inline std::string addMoreDetail (std::string& s) const {return s + " Detail1";}
};
template <int N>
class Derived<N, 0, 1> : public Derived<N, 0> {
public:
virtual std::string description() const override {
std::string str = Derived<N, 0>::description(); return this->finalize(str);
// Can this be moved up somehow?
}
private:
inline std::string addMoreDetail (std::string& s) const {return s + " Detail2";}
};
int main() {
std::cout << Derived<0, 0, 0>().description() << '\n'; // Whatever1
std::cout << Derived<0, 0, 1>().description() << '\n'; // Whatever1
std::cout << Derived<1, 0, 0>().description() << '\n'; // Whatever2 Detail1
std::cout << Derived<1, 0, 1>().description() << '\n'; // Whatever2 Detail2
}
我的目标很简单。我想避免写作
std::string str = Derived<N, 0>::description(); return this->finalize(str);
在层次结构中向上移动两次。
这是我的临时解决方案:
#include <iostream>
#include <string>
template <int...> class Derived;
class Base {
protected:
virtual std::string description() const = 0;
virtual std::string addMoreDetail (std::string&) const = 0;
template <int N> std::string descriptionBase (const Derived<N, 0>* derived) const {
// std::string str = derived->description(); return derived->finalize(str); // Endless look-up!
std::string str = derived->staticDescription(); return derived->finalize(str);
}
};
template <>
class Derived<0, 0> : protected Base {
private:
bool b;
friend Base;
protected:
virtual std::string description() const {return staticDescription();}
static std::string staticDescription() {return "Whatever1";}
std::string finalize (std::string& str) const {return b ? addMoreDetail(str) : str;}
};
template <>
class Derived<1, 0> : protected Base {
friend Base;
protected:
virtual std::string description() const {return staticDescription();}
static std::string staticDescription() {return "Whatever2";}
std::string finalize (std::string& str) const {return addMoreDetail(str);}
};
template <int N>
class Derived<N, 0, 0> : public Derived<N, 0> {
public:
std::string description() const override {return this->template descriptionBase<N>(this);}
private:
inline std::string addMoreDetail (std::string& s) const {return s + " Detail1";}
};
template <int N>
class Derived<N, 0, 1> : public Derived<N, 0> {
public:
std::string description() const override {return this->template descriptionBase<N>(this);}
private:
inline std::string addMoreDetail (std::string& s) const {return s + " Detail2";}
};
int main() {
std::cout << Derived<0, 0, 0>().description() << '\n'; // Whatever1
std::cout << Derived<0, 0, 1>().description() << '\n'; // Whatever1
std::cout << Derived<1, 0, 0>().description() << '\n'; // Whatever2 Detail1
std::cout << Derived<1, 0, 1>().description() << '\n'; // Whatever2 Detail2
}
但是这在我的程序中实际上并不起作用,因为description()
不是静态的,因为它依赖于数据成员。但是,如果我使用
std::string str = derived->description(); return derived->finalize(str);
而不是
std::string str = derived->staticDescription(); return derived->finalize(str);
我得到了一个无休止的运行时虚拟查找,因为它不断回到原始状态。怎么避免这个?或者有更好的方法来实现我的目标吗?
答案 0 :(得分:1)
使您的staticDescription
方法成为非虚拟非静态成员函数,即保持代码不变,并在定义static
方法时删除staticDescription
。您可能希望将staticDescription
重命名为doGetDescription
左右。
通常的解决方案可能是使用模板方法模式(或非虚拟接口模式):
class BaseClass {
public:
std::string getDescription () const {
return this->doGetDescription ();
}
private:
virtual std::string doGetDescription () const = 0;
};
class FirstDerived : public BaseClass {
std::string doGetDescription () const override { return "First"; }
};
class SecondDerived : public BaseClass {
std::string doGetDescription () const override { return "Second"; }
};
BaseClass & b = SecondDerived {};
std::cout << b.getDescription () << std::endl;