基本上我有一个课程,让我们说Parameter
有一个get和set变量。
我还有一个基类让我们说Vehicle
有一个方法registerParameter(...)
,它将一个指向函数成员的指针作为getter,一个指向函数成员的指针作为setter。然后,该方法应该将这两个指针写入参数类的对象,并将此对象抛出到向量中。
最后但并非最不重要的是,我们有一个派生类,让我们说Car
,我们用registerParameter(...)
作为参数名称调用"color"
,并使用此函数调用getter和setter衍生类。
代码示例:
参数文件
#ifndef BASE_H
#define BASE_H
#include "base.h"
class Parameter
{
std::string (Base::*get)();
void (Base::*set)(std::string);
};
#endif
基础文件
#ifndef PARAMETER_H
#define PARAMETER_H
#include <vector>
#include "parameter.h"
class Base
{
public:
std::vector<Parameter> list;
void registerNew(std::string (Base::*get)(), void (Base::*set)(std::string))
{
Parameters parameter;
parameter.get = get;
parameter.set = set;
list.push_back(parameter);
}
};
#endif
派生文件
class Derived
{
public:
Derived derived()
{
registerNew(&getColor, &setColor);
}
std::string getColor()
{
return this->color;
}
std::string setColor(std::string newColor)
{
this->color = newColor;
}
private:
std::string color;
};
我几天来一直在考虑这个问题,直到星期五晚上我才真正需要这个解决方案。
答案 0 :(得分:1)
你不能做正在尝试的事情:
std::string (Base::*)()
和std::string (Derived::*)()
类型非常不同。 std::string (Derived::*)()
无法自动转换为std::string (Base::*)()
。
采取以下方案。
struct Base
{
int foo() { return 10; }
};
struct Derived : Base
{
int bar() { return 20; }
};
int main()
{
Base base;
int (Base::*bf)() = &Base::foo;
(base.*bf)(); // Should be able to call Base:foo(). No problem.
bf = &Derived::bar; // This is a compiler error. However, if this were allowed....
(base.*bf)(); // Call Derived::bar()?? That will be a problem. base is not an
// instance of Derived.
}
<强>更新强>
您可以执行以下操作:
#include <string>
#include <vector>
class Base;
// Create a base class Functor that provides the interface to be used by
// Base.
struct Functor
{
virtual ~Functor() {}
virtual std::string get(Base& base) = 0;
virtual void set(Base& base, std::string) = 0;
};
// Create a class template that implements the Functor interface.
template <typename Derived> struct FunctorTemplate : public Functor
{
// typedefs for get and set functions to be used by this class.
typedef std::string (Derived::*GetFunction)();
typedef void (Derived::*SetFunction)(std::string);
// The constructor that uses the get and set functions of the derived
// class to do itw work.
FunctorTemplate(GetFunction get, SetFunction set) : get_(get), set_(set) {}
virtual ~FunctorTemplate() {}
// Implement the get() function.
virtual std::string get(Base& base)
{
return (reinterpret_cast<Derived&>(base).*get_)();
}
// Implement the set() function.
virtual void set(Base& base, std::string s)
{
(reinterpret_cast<Derived&>(base).*set_)(s);
}
GetFunction get_;
SetFunction set_;
};
class Base
{
public:
std::vector<Functor*> functorList;
void registerFunctor(Functor* functor)
{
functorList.push_back(functor);
}
};
class Derived : public Base
{
public:
Derived()
{
// Register a FunctorTemplate.
registerFunctor(new FunctorTemplate<Derived>(&Derived::getColor,
&Derived::setColor));
}
std::string getColor()
{
return this->color;
}
void setColor(std::string newColor)
{
this->color = newColor;
}
private:
std::string color;
};
答案 1 :(得分:0)
您的基类应该知道派生类。这听起来很复杂,但问题已经解决了:
template<typename DERIVED> class Base
{
public:
class Parameter {
std::string (DERIVED::*get)();
void (DERIVED::*set)();
};
private:
std::list<Parameter> list;
// ...
};
class Derived : public Base<Derived> // !!!
{
registerNew(&Derived::getColor, &Derived::setColor);
};
此解决方案称为奇怪的重复模板模式(CRTP)。