避免无休止的虚拟查找
Avoiding endless virtual look-up
考虑这段代码:
#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);
我进行了 运行 次无休止的虚拟查找,因为它不断返回到原始位置。如何避免这种情况?或者有更好的方法来实现我的目标吗?
使您的 staticDescription
方法成为非虚拟非静态成员函数,即保持代码不变,并在定义 staticDescription
方法时删除 static
。也许您想将 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;
考虑这段代码:
#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);
我进行了 运行 次无休止的虚拟查找,因为它不断返回到原始位置。如何避免这种情况?或者有更好的方法来实现我的目标吗?
使您的 staticDescription
方法成为非虚拟非静态成员函数,即保持代码不变,并在定义 staticDescription
方法时删除 static
。也许您想将 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;